簡體   English   中英

笛卡爾積沒有重復

[英]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具有SetMap ,但它們通過引用而不是值來比較對象和數組,因此您無法直接利用它。 我們的想法是使用一個鍵函數,在將它放入集合之前對其進行排序和json編碼。

純ES5:

 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> 

lodash + 現代JavaScript

// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM