[英]How can I create all combinations of this object's keys/values in JavaScript?
我有以下 JavaScript 對象結構:
var options = {
optionOne: [true, false],
optionTwo: [true, false],
optionThree: [
null,
{property1: 9, property2: 7},
{property1: 4, property2: 12},
{property1: 16, property2: 14}
]
};
請注意,此對象中的密鑰/對的數量會有所不同。 所以實際上可能有optionFour
、 optionFive
等,並且每個選項的數組可以有任意數量或類型的值。
我需要遍歷這個對象並創建一個包含所有可能選項組合的對象的數組:
[
{optionOne: true, optionTwo, true, optionThree: null},
{optionOne: false, optionTwo, true, optionThree: null},
{optionOne: true, optionTwo, false, optionThree: null},
{optionOne: false, optionTwo, false, optionThree: null},
{optionOne: true, optionTwo, true, optionThree: {property1: 9, property2: 7}},
{optionOne: false, optionTwo, true, optionThree: {property1: 9, property2: 7}},
{optionOne: true, optionTwo, false, optionThree: {property1: 9, property2: 7}},
{optionOne: false, optionTwo, false, optionThree: {property1: 9, property2: 7}},
{optionOne: true, optionTwo, true, optionThree: {property1: 4, property2: 12}},
{optionOne: false, optionTwo, true, optionThree: {property1: 4, property2: 12}},
{optionOne: true, optionTwo, false, optionThree: {property1: 4, property2: 12}},
{optionOne: false, optionTwo, false, optionThree: {property1: 4, property2: 12}},
{optionOne: true, optionTwo, true, optionThree: {property1: 16, property2: 14}},
{optionOne: false, optionTwo, true, optionThree: {property1: 16, property2: 14}},
{optionOne: true, optionTwo, false, optionThree: {property1: 16, property2: 14}},
{optionOne: false, optionTwo, false, optionThree: {property1: 16, property2: 14}}
]
我正在努力解決這個問題,但我相當有信心答案在於遞歸。
算法大神能幫幫我嗎?
function getCombinations(options, optionIndex, results, current) {
var allKeys = Object.keys(options);
var optionKey = allKeys[optionIndex];
var vals = options[optionKey];
for (var i = 0; i < vals.length; i++) {
current[optionKey] = vals[i];
if (optionIndex + 1 < allKeys.length) {
getCombinations(options, optionIndex + 1, results, current);
} else {
// The easiest way to clone an object.
var res = JSON.parse(JSON.stringify(current));
results.push(res);
}
}
return results;
}
像這樣使用它:
var results = getCombinations(options, 0, [], {});
這是一個有效的JSFiddle 示例。
這是最近復活的,我認為現代 JS 提供了一種更簡潔的方式來編寫它。
const crossproduct = (xss) => xss.reduce((xs, ys) => xs.flatMap(x => ys.map(y => [...x, y])), [[]]) const combinations = (o, keys = Object .keys (o), vals = Object .values (o)) => crossproduct(vals).map(xs => Object.fromEntries(xs.map ((x, i) => [keys[i], x]))) const options = {optionOne: [true, false], optionTwo: [true, false], optionThree: [null, {property1: 9, property2: 7}, {property1: 4, property2: 12}, {property1: 16, property2: 14}]} console .log (JSON .stringify ( combinations (options) , null, 4))
.as-console-wrapper {max-height: 100% !important; top: 0}
我們從一個crossproduct
函數開始,例如,它需要
[[1, 2], ['a', 'b', 'c'], ['T', 'F']]
並返回
[
[1, 'a', 'T'], [1, 'a', 'F'], [1, 'b', 'T'], [1, 'b', 'F'], [1, 'c', 'T'], [1, 'c', 'F'],
[2, 'a', 'T'], [2, 'a', 'F'], [2, 'b', 'T'], [2, 'b', 'F'], [2, 'c', 'T'], [2, 'c', 'F']
]
然后combinations
使用Object.keys
和Object.values
將我們的對象分開,將值傳遞給crossproduct
,然后對於結果中的每個數組,映射值,將相應的鍵與每個值相關聯,然后使用Object.fromEntries
重新混合對象.
這個順序對我來說似乎是結果的邏輯順序。 但是,如果我們將返回的crossproduct
表達式替換為以下內容,我們將得到問題中提到的順序:
xss .reduce ((xs, ys) => ys .flatMap (y => xs .map (x => [...x, y])), [[]])
這是基於 Dmytro 的回答的改進:
function getPermutations(object, index = 0, current = {}, results = []) {
const keys = Object.keys(object);
const key = keys[index];
const values = object[key];
for (const value of values) {
current[key] = value;
const nextIndex = index + 1;
if (nextIndex < keys.length) {
this.getPermutations(object, nextIndex, current, results);
} else {
const result = Object.assign({}, current);
results.push(result);
}
}
return results;
}
改進:
const p = getPermutations(object);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.