如何在 JavaScript 中创建此对象的 keys/values 的所有组合?
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}
]
};
请注意,此对象中 key/pairs 的数量会有所不同。所以实际上可能有 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 example。
这是一个改进,基于 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);
- 细微的语义改进
最近复活了,我认为现代 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']]
和returns
[
[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])), [[]])
我有以下 JavaScript 对象结构:
var options = {
optionOne: [true, false],
optionTwo: [true, false],
optionThree: [
null,
{property1: 9, property2: 7},
{property1: 4, property2: 12},
{property1: 16, property2: 14}
]
};
请注意,此对象中 key/pairs 的数量会有所不同。所以实际上可能有 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 example。
这是一个改进,基于 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);
- 细微的语义改进
最近复活了,我认为现代 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']]
和returns
[
[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])), [[]])