2017-11-10 19 views
-1

オブジェクト内の配列値をフラットにしたいと思います。下記のsampleのようになります。この解決策は、ecommerceにのみ適用されるのではなく、文字通り配列型としてオブジェクト内に存在する可能性があるものをすべて使用してください。例:私は出力になりたいJavascript:オブジェクト内の配列値を均等化する(ネストされた)

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" 
    } 
    } 
} 

のJavaScript(ES6/7)でこれを行うための最も効率的な方法は何ですか?

ありがとうございます!

コメントといくつかのマイナスのために更新されました!質問が最初に尋ねられたときにマイナスをクリックするのが速かった人がそれを取り消すなら、いいでしょう。

私はその完全に間違ってこれを試してみたと私も確信しているが、これを行うためのより良い機能的な方法をtheresの:

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:両方のソリューションはecommerceどのようにとても執着したようが見て次のオブジェクトは、ソリューションの仕事だったかどう:その、あまりにも異なるのネストレベルでこの異なるkeyであるだけでなく、

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

お知らせ。私はどうだろう何

+0

どのようにあなたの現在の実装だ...ので、1が重複したロジックを取り除くかもしれないステップを消毒二つの機能との交流/相反再帰で終わりますか? – mersocarlin

+0

...これを確認してください[一般的に 'Array#reduce'に基づくアプローチ](https://stackoverflow.com/questions/47221864/javascript-flatten-any-array-values-within-object-nested/47266505#47266505 )は、2つのソリューションを提供します.1つは単純な再帰で、もう1つは交互/逆数再帰を使用します。おかげさまで –

答えて

1

Aは、再帰的にArray#reduceベースのアプローチは、キーと値のバッグのこの種の仕事をしていません適用され、...最初の一般的な解決策は、...この1のようになります

次のコード内

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

質問に答えるためにピーターに感謝します - 例では、これは確かに仕事をするように見えます。議決権を行使し、何か問題があれば返信します。再度、感謝します :) – 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

ありがとうございました。しかし、以前の回答によると、これはオブジェクトの 'eコマース'部分に非常に特有です。私はすべてのキー/値のペアに対して可能な限り深くネストする必要があります。 。 – sukh

関連する問題