2017-11-10 2 views
-1

어떤 객체 내에서 배열 값을 평평하게하고 싶습니다. 아래 sample과 같습니다. 해결책은 ecommerce에 적용해서는 안되며 글자 그대로 객체에 배열 유형으로 포함될 수있는 모든 것을 적용해야합니다. 예 : I 출력이되고 싶습니다자바 스크립트 : 객체 (배열 된) 내 모든 배열 값을 평평하게합니다.

var sample = { 
    price: "999", 
    description: "...", 
    ecommerce: { 
    products: [ 
     { 
     brand: "apple", 
     category: "phone" 
     }, 
     { 
     brand: "google", 
     category: "services" 
     } 
    ] 
    } 
}; 

그리고 :

{ 
    price: "999", 
    description: "..." 
    ecommerce: { 
    products_1: { 
     brand: "apple", 
     category: "phone" 
    }, 
    products_2: { 
     brand: "google", 
     category: "services" 
    } 
    } 
} 

자바 스크립트 (ES6/7)에서이 작업을 수행하는 가장 효율적인 방법은 무엇입니까?

미리 감사드립니다.

의견 및 여러 개의 분노로 인해 업데이트되었습니다. 질문이 처음 요청되었을 때 너무 빨리 빠져 나간 사람들이 그것을 취소하면 좋을까요?

나는이 그 완전히 잘못 시도하고 확실 프로그래머에게이 일을 더 나은 기능 방법이야 : 두 솔루션은 ecommerce 방법에 너무 집착했다으로보고 :

function flattenArray(array) { 

    var obj = array.reduce((acc, cur, i) => { 
    acc[i] = cur; 
    return acc; 
    }, {}); 

    return obj; 
} 

function cleanObject(object) { 
    for (let key in object) { 
    let testObject = object[key]; 

    if (Array.isArray(testObject)) { 
     testObject = flattenArray(testObject) 
    } else if (typeof(testObject) === 'object') { 
     testObject = cleanObject(testObject); 
    } 

    return testObject; 
    } 

    return object; 
} 

var clean = cleanObject(sample); 

UPDATE (2) 다음 개체는 솔루션의 일이었다 할 경우 : 그 또한 너무 다른 중첩 수준에서이 다른 key입니다뿐만 아니라

var sample = { 
    price: "999", 
    description: "...", 
    differentArray: [ 
    { 
     brand: "apple", 
     category: "phone" 
    }, 
    { 
     brand: "google", 
     category: "services" 
    } 
    ] 
}; 

공지 사항. 내가 할 줄 무엇

+0

어떻게 현재의 구현입니다 ... 따라서, 하나는 중복 로직을 제거 할 수 단계를 살균 두 가지 기능 및 교류/상호 재귀로 결말? – mersocarlin

+0

...이 [일반적으로'Array # reduce' 기반 접근법] (https://stackoverflow.com/questions/47221864/javascript-flatten-any-array-values-within-object-nested/47266505#47266505)을 확인하십시오.)는 두 가지 솔루션을 제공합니다. 하나는 간단한 재귀와 함께 제공되고 두 번째는 교대/역방향 재귀를 사용합니다. –

답변

1

A는 반복적으로 Array#reduce 기반의 접근 방식은 키 - 값 가방 이런 종류의 일을 적용, ... 첫 번째 일반적인 해결책은 ... 이것처럼 보일 수 있습니다

다음 코드 내

function recursivelyMapArrayItemsToGenericKeys(collector, key) { 
 
    var 
 
    source = collector.source, 
 
    target = collector.target, 
 
    type = source[key]; 
 

 
    if (Array.isArray(type)) { 
 
    type.forEach(function (item, idx) { 
 
     var 
 
     keyList  = Object.keys(item || ''), 
 
     genericKey = [key, idx].join('_'); 
 

 
     if (keyList.length >= 1) { 
 
     target[genericKey] = keyList.reduce(recursivelyMapArrayItemsToGenericKeys, { 
 

 
      source: item, 
 
      target: {} 
 

 
     }).target; 
 
     } else { 
 
     target[genericKey] = item; 
 
     } 
 
    }); 
 
    } else if (typeof type !== 'string') { 
 
    var keyList = Object.keys(type || ''); 
 

 
    if (keyList.length >= 1) { 
 
     target[key] = keyList.reduce(recursivelyMapArrayItemsToGenericKeys, { 
 

 
     source: type, 
 
     target: {} 
 

 
     }).target; 
 
    } else { 
 
     target[key] = type; 
 
    } 
 
    } else { 
 
    target[key] = type; 
 
    } 
 
    return collector; 
 
} 
 

 
var sample = { 
 
    price: "999", 
 
    description: "...", 
 
    ecommerce: { 
 
    products: [{ 
 
     brand: "apple", 
 
     category: "phone" 
 
    }, { 
 
     brand: "google", 
 
     category: "services" 
 
    }, { 
 
     foo: [{ 
 
     brand: "bar", 
 
     category: "biz" 
 
     }, { 
 
     brand: "baz", 
 
     category: "biz" 
 
     }] 
 
    }] 
 
    } 
 
}; 
 

 
var result = Object.keys(sample).reduce(recursivelyMapArrayItemsToGenericKeys, { 
 

 
    source: sample, 
 
    target: {} 
 

 
}).target; 
 

 
console.log('sample : ', sample); 
 
console.log('result : ', result);
.as-console-wrapper { max-height: 100%!important; top: 0; }

...

function recursivelyAssignItemsFromTypeByKeys(target, type, keyList, key) { 
 
    if (keyList.length >= 1) { 
 
    target[key] = keyList.reduce(recursivelyMapArrayItemsToGenericKeys, { 
 

 
     source: type, 
 
     target: {} 
 

 
    }).target; 
 
    } else { 
 
    target[key] = type; 
 
    } 
 
} 
 

 
function recursivelyMapArrayItemsToGenericKeys(collector, key) { 
 
    var 
 
    source = collector.source, 
 
    target = collector.target, 
 
    type = source[key]; 
 

 
    if (Array.isArray(type)) { 
 
    type.forEach(function (item, idx) { 
 
     var 
 
     keyList  = Object.keys(item || ''), 
 
     genericKey = [key, idx].join('_'); 
 

 
     recursivelyAssignItemsFromTypeByKeys(target, item, keyList, genericKey); 
 
    }); 
 
    } else if (typeof type !== 'string') { 
 
    var keyList = Object.keys(type || ''); 
 

 
    recursivelyAssignItemsFromTypeByKeys(target, type, keyList, key); 
 
    } else { 
 
    target[key] = type; 
 
    } 
 
    return collector; 
 
} 
 

 
var sample = { 
 
    price: "999", 
 
    description: "...", 
 
    ecommerce: { 
 
    products: [{ 
 
     brand: "apple", 
 
     category: "phone" 
 
    }, { 
 
     brand: "google", 
 
     category: "services" 
 
    }, { 
 
     foo: [{ 
 
     brand: "bar", 
 
     category: "biz" 
 
     }, { 
 
     brand: "baz", 
 
     category: "biz" 
 
     }] 
 
    }] 
 
    } 
 
}; 
 

 
var result = Object.keys(sample).reduce(recursivelyMapArrayItemsToGenericKeys, { 
 

 
    source: sample, 
 
    target: {} 
 

 
}).target; 
 

 
console.log('sample : ', sample); 
 
console.log('result : ', result);
.as-console-wrapper { max-height: 100%!important; top: 0; }

+0

피터 (Peter)가 질문에 답해 주신 것에 대해 감사드립니다. 투표를 올리고 어떤 문제가 있으면 다시 게시 할 것입니다. 다시 한번 감사드립니다 :) – sukh

0

:

const sample = { 
 
    price: "999", 
 
    description: "...", 
 
    ecommerce: { 
 
    products: [ 
 
     { 
 
     brand: "apple", 
 
     category: "phone" 
 
     }, 
 
     { 
 
     brand: "google", 
 
     category: "services" 
 
     } 
 
    ] 
 
    } 
 
} 
 

 
sample.ecommerce.products.forEach((p, i) => { 
 
    sample.ecommerce['products_' + i] = p 
 
}) 
 

 
delete sample.ecommerce.products 
 

 
console.log(sample)

+0

감사합니다.그러나 내가 원한 것은 이것에 대해 불가지론 적이며'ecommerce.products'의 특정 사용 사례에만 적용되는 것이 아닙니다. 내가 돌아올 객체는 알 수없는 키/값을 갖습니다. 배열은 배열이 될 수도 있고 아닐 수도 있습니다. – sukh

0

그냥 reduceecommerce 배열을 원하는대로 각 요소를 폭파.

const sample = { 
 
    price: "999", 
 
    description: "...", 
 
    ecommerce: { 
 
    products: [ 
 
     { 
 
     brand: "apple", 
 
     category: "phone" 
 
     }, 
 
     { 
 
     brand: "google", 
 
     category: "services" 
 
     } 
 
    ] 
 
    } 
 
} 
 

 
const flattenArray = (arr, key) => 
 
    arr.reduce((prev, curr, index) => { 
 
    return { 
 
     ...prev, 
 
     [`${key}_${index + 1}`]: curr, 
 
    } 
 
    }, {}) 
 
    
 
const result = { 
 
    ...sample, 
 
    ecommerce: flattenArray(sample.ecommerce.products, 'products'), 
 
} 
 

 
console.log(result)

+0

고마워요.하지만 이전 답변에 따르면 이것은 객체의 '전자 상거래'부분에 매우 구체적입니다. 모든 키/값 쌍에 대해 가능한 한 많이 중첩해야하고, 배열인지 확인한 다음 그에 따라 평평하게 배열해야합니다. . – sukh