簡體   English   中英

javascript中對象的笛卡爾積

[英]Cartesian product of objects in javascript

我需要根據N個屬性列表生成一組完整的變體,同時保持屬性名稱不變。

var input = [
    { 'colour' : ['red', 'green'] },
    { 'material' : ['cotton', 'wool', 'silk'] },
    { 'shape' : ['round', 'square', 'rectangle'] }
];

var expected = [
    { 'colour': 'red', 'material': 'cotton', 'shape': 'round' },
    { 'colour': 'red', 'material': 'cotton', 'shape': 'square' },
    { 'colour': 'red', 'material': 'cotton', 'shape': 'rectangle' },
    { 'colour': 'red', 'material': 'wool', 'shape': 'round' },
    { 'colour': 'red', 'material': 'wool', 'shape': 'square' },
    { 'colour': 'red', 'material': 'wool', 'shape': 'rectangle' },
    { 'colour': 'red', 'material': 'silk', 'shape': 'round' },
    { 'colour': 'red', 'material': 'silk', 'shape': 'square' },
    { 'colour': 'red', 'material': 'silk', 'shape': 'rectangle' },
    { 'colour': 'green', 'material': 'cotton', 'shape': 'round' },
    { 'colour': 'green', 'material': 'cotton', 'shape': 'square' },
    { 'colour': 'green', 'material': 'cotton', 'shape': 'rectangle' },
    { 'colour': 'green', 'material': 'wool', 'shape': 'round' },
    { 'colour': 'green', 'material': 'wool', 'shape': 'square' },
    { 'colour': 'green', 'material': 'wool', 'shape': 'rectangle' },
    { 'colour': 'green', 'material': 'silk', 'shape': 'round' },
    { 'colour': 'green', 'material': 'silk', 'shape': 'square' },
    { 'colour': 'green', 'material': 'silk', 'shape': 'rectangle' }
];

對於數組的笛卡爾積,有很多算法,但我似乎找不到保留鍵的對象。

性能不是一個大問題,因為每個屬性永遠不會有超過十幾個值。 訂單不必與expected完全匹配。

我已根據列表的標准算法進行了初步嘗試,但我正在努力:

function cartesianProduct(input, current) {
    if (!input || input.length < 1) {
        return [];
    }

    var head = input[0];
    var tail = input.slice(1);
    var output = [];

    for (var key in head) {
        for (var i = 0; i < head[key].length; i++) {
            if (typeof current == 'undefined') {
                var current = {};
            }

            current[key] = head[key][i];
            var productOfTail = cartesianProduct(tail, current);
            output.push(current);
            console.log(current);
        }
    }

    return output;
}

console.log(cartesianProduct(input));

一旦你擺脫''i'是一個全局變量問題',你可以用這個代碼得到結果:

var input = [
    { 'colour' : ['red', 'green'] },
    { 'material' : ['cotton', 'wool', 'silk'] },
    { 'shape' : ['round', 'square', 'rectangle'] }
];

function cartesianProduct(input, current) {
   if (!input || !input.length) { return []; }

   var head = input[0];
   var tail = input.slice(1);
   var output = [];

    for (var key in head) {
      for (var i = 0; i < head[key].length; i++) {
            var newCurrent = copy(current);         
            newCurrent[key] = head[key][i];
            if (tail.length) {
                 var productOfTail = 
                         cartesianProduct(tail, newCurrent);
                 output = output.concat(productOfTail);
            } else output.push(newCurrent);
       }
     }    
    return output;
}

function copy(obj) {
  var res = {};
  for (var p in obj) res[p] = obj[p];
  return res;
}


console.log(cartesianProduct(input));

下面是使用Ramda.js的解決方案

 const input = [ { 'colour': ['red', 'green'] }, { 'material': ['cotton', 'wool', 'silk'] }, { 'shape': ['round', 'square', 'rectangle'] } ] const cartesianProductList = (Xs) => ( R.reduce( (Ys, X) => ( R.map(R.apply(R.append), R.xprod(X, Ys)) ), [[]], Xs ) ) const xPairs = (x, xs) => ( R.map(R.pair(x), xs) ) const cartesianProductObject = (objs) => ( R.pipe( R.mergeAll, R.toPairs, R.map(R.apply(xPairs)), cartesianProductList, R.map(R.fromPairs), )(objs) ) console.log(cartesianProductObject(input)) 
 <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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