[英]Cartesian product without duplicates
我正在使用笛卡尔积函数给出[1], [1,2,3], [1,2,3]
返回9种组合:
[ [ 1, 1, 1 ],
[ 1, 2, 1 ],
[ 1, 3, 1 ],
[ 1, 1, 2 ],
[ 1, 2, 2 ],
[ 1, 3, 2 ],
[ 1, 1, 3 ],
[ 1, 2, 3 ],
[ 1, 3, 3 ] ]
但是无论顺序如何,我都需要删除那些具有相同项目的项目,因此[ 1, 3, 1 ]
和[ 1, 1, 3 ]
对我来说是一样的。 结果应包含6个项目:
[ [ 1, 1, 1 ],
[ 1, 2, 1 ],
[ 1, 3, 1 ],
[ 1, 2, 2 ],
[ 1, 3, 2 ],
[ 1, 3, 3 ] ]
我可以编写一个函数来比较所有可能的对与_.xor
,但对于较大的数字,它可能效率非常低。 有没有一个很好的方法在Javascript中执行此操作? 比较所有可能的对或笛卡尔积的算法而不重复的有效方法?
对笛卡尔积的每个数组进行排序
[ 1, 2, 1 ] -> [1 , 1 , 2]
[ 1, 1, 2 ] -> [1 , 1 , 2]
然后将这些排序的数组收集到一个集合中,这将删除重复项。
当然,你可以在构建笛卡尔积而不是之后的同时做到这一点。
JavaScript具有Set和Map ,但它们通过引用而不是值来比较对象和数组,因此您无法直接利用它。 我们的想法是使用一个键函数,在将它放入集合之前对其进行排序和json编码。
function product(sets) { if (sets.length > 0) { var head = sets[0]; var tail = product(sets.slice(1)); var result = []; head.forEach(function(x) { tail.forEach(function(xs) { var item = xs.slice(0); item.unshift(x); result.push(item); }); }); return result; } else { return [[]]; } } function myKeyFn(item) { return JSON.stringify(item.slice(0).sort()); } function uniqBy(items, keyFn) { var hasOwn = Object.prototype.hasOwnProperty, keyset = {}; return items.filter(function(item) { var key = keyFn(item); if (hasOwn.call(keyset, key)) { return false; } else { keyset[key] = 1; return true; } }); } function uniqProduct(sets) { return uniqBy(product(sets), myKeyFn); } function log(x) { console.log(x); var pre = document.createElement('pre'); pre.appendChild(document.createTextNode(x)); document.body.appendChild(pre); } log(uniqProduct([[1],[1,2,3],[1,2,3]]).map(JSON.stringify).join("\\n"));
<pre></pre>
// Note: This doesn't compile on current babel.io/repl due to a bug
function product(sets) {
if (sets.length > 0) {
const [x, ...xs] = sets;
const products = product(xs);
return _.flatMap(x, head => products.map(tail => [head, ...tail]));
} else {
return [[]];
}
}
function uniqProduct(sets) {
return _.uniqBy(product(sets), x => JSON.stringify(x.slice(0).sort()));
}
console.log(uniqProduct([[1],[1,2,3],[1,2,3]]).map(JSON.stringify).join("\n"));
JavaScript已设置数据结构。
因此,将结果存储在一个集合中,集合中的每个元素都是原始集合中数字对的集合,以及该数字出现的次数。
所以你的结果看起来像这样:
[
{1:3},
{1:2, 2: 1},
{ 1:2, 3:1},
{ 1:1, 2:2},
{ 1:1, 2:1, 3:1},
{ 1:1, 3:2 } ]
这样,您将无法再次将对象添加到集合中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.