我正在尝试从约束哈希生成所有可能的对象。
让我们说约束是:
{
key1: [ 'possible value1' , 'possible value2' ],
key2: [ 2, 4, 7, 1],
...
}
我想生成所有可能的对象:
{ key1: 'possible value1', key2: 2 }
{ key1: 'possible value1', key2: 4 }
...
有人能指出我正确的方向吗?
谢谢!
答案 0 :(得分:2)
var options = {
key1: [ 'possible value1' , 'possible value2'],
key2: [ 2, 4, 7, 1],
key3: ['TEST1', 'TEST2']
};
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 {
var res = JSON.parse(JSON.stringify(current));
results.push(res);
}
}
return results;
}
var results = getCombinations(options, 0, [], {});
document.body.innerHTML = JSON.stringify(results);
&#13;
答案 1 :(得分:1)
let constraints = {
key1: ['possible value1' , 'possible value2'],
key2: [2, 4, 7, 1],
key3: ["foo", "bar"],
};
let result = Object.keys(constraints).reduce(
(acc, key) =>
acc.map(a1 =>
constraints[key].map(a2 =>
a1.concat([a2])
)
).reduce((e1, e2) => e1.concat(e2)),
[[]]
);
console.log(JSON.stringify(result));
首先,如果第一个包含数组(由一些约束集生成的所有数组)和第二个单个元素(一个新约束),我们首先确保知道如何对两个数组的所有元素进行连接。 (例如[["possible value1"], ["possible value2"]
和[1, 2]
)。我们映射一个数组,映射另一个数组,然后将它们粘在一起(a1
和a2
地图,a1.concat([a2])
)。嵌套的map
将生成一个两级数组,因此我们将只连接单个级别的所有数组(内部reduce
)。
请注意,如果我们将空数组连接到数组,则数组不会更改;因此,我们可以引入另一个约束,一个空约束:[]
。如果我们将与此约束对应的所有数组[[]]
与["possible value1", "possible value2"]
组合在一起,我们仍会得到相同的集合。这是我们的外部reduce
的起始值:从这个“null元素”开始,我们可以连接其他约束,如上所述。
let constraints = {
key1: ['possible value1' , 'possible value2'],
key2: [2, 4, 7, 1],
key3: ["foo", "bar"],
};
const unconstrainedPossibilities = [[]];
const flatten = array => array.reduce((a1, a2) => a1.concat(a2));
const addConstraint = (possibilities, constraint) =>
flatten(
possibilities.map(possibility =>
constraint.map(constraintValue =>
possibility.concat([constraintValue])
)
)
);
const possibilitiesFor = constraints =>
constraints.reduce(
(possibilities, constraint) => addConstraint(possibilities, constraint),
unconstrainedPossibilities
);
let possibilities = possibilitiesFor(Object.values(constraints));
console.log(JSON.stringify(possibilities));
答案 2 :(得分:0)
我知道有更优雅的方法可以做到这一点,但我想提出一个并没有真正涉及太多思考的算法,所以,我的想法只是使用一个基本的while
循环循环的每次迭代创建下一个组合并将其粘贴在输出数组中。
我首先创建一个keys
数组,其中包含{k: "key1", index: 0, length: 2}
形式中每个键的对象 - 基本上是为了跟踪该键,我们在其数组中使用哪个索引,它的数组有多长。然后while
循环的第一行使用.reduce()
使用每个键的当前索引的值构建一个对象,然后使用for
循环移动到下一个组合。当它到达组合的末尾时,它会突破while
循环。
const constraints = {
key1: ['pv1', 'pv2', 'pv3', 'pv4'],
key2: [2, 4, 7, 1],
key3: ['a', 'b'],
key4: [10, 20, 30]
}
const output = []
const keys = Object.keys(constraints)
.map(k => ({ k: k, index: 0, length: constraints[k].length }))
process: while (true) {
output.push(keys.reduce((a, c) => {
a[c.k] = constraints[c.k][c.index];
return a;
}, {}))
for (let i = keys.length - 1; i >= 0; i--) {
keys[i].index++
if (keys[i].index < keys[i].length) break
if (i === 0) break process
keys[i].index = 0
}
}
console.log(JSON.stringify(output))
&#13;