如何在数组数组中连接每个独特的可能性

时间:2015-04-10 12:28:22

标签: javascript jquery

我在一个数组中有以下两个数组:

var arrayOfArrays = [['apple', 'banana'], ['carrot', 'leek']];

我希望将第一个数组中的所有选项与第二个数组中的所有选项连接起来。所以我会得到以下4个结果:

var result = ['applecarrot', 'appleleek', 'bananacarrot', 'bananaleek'];

解决方案应该适用于任意数量的子阵列。所以我们可以有一系列水果,蔬菜和鲜花,每个都包含n个项目。每个结果还必须包含每个子数组中的一个单词。因此,如果有3个子阵列,则所有结果将包含3个单词。

3个数组的示例:

var arrayOfArrays = [['apple', 'banana'], ['carrot', 'leek'], ['rose', 'lily'];
var result = ['applecarrotrose', 'applecarrotlily', 'appleleekrose', 'appleleeklily', 'bananacarrotrose', 'bananacarrotlily', 'bananaleekrose', 'bananaleeklily'];

我提出了以下内容,但它似乎只生成了['applecarrot', 'appleleek']

combination(arrayOfArrays, '');

var strings = [];

function combination(array, str) {
    var current = array.shift();

    if (array.length > 0) {
        $.each(current, function(i,v) {
            combination(array, str + v);
        });
    } else {
        $.each(current, function(i,v) {
            strings.push(str + v);
        });
    }
}

4 个答案:

答案 0 :(得分:3)

没有任何内置的方式你必须自己制作。 Fist off没有任何需要在数组中有一个数组。你唯一真正处理两个选项(基本数组和一个或多个修饰符数组)所以你可以构造一个迭代它们的函数:

function combiner(base, subject) {
  return base.reduce(function(memo, baseValue) {
    subject.forEach(function(subjectValue) {
      memo.push(baseValue + subjectValue);
    });
    return memo;
  }, []);
}

var arrayOfArrays = [['apple', 'banana'], ['carrot', 'leek']];
var result = combiner(arrayOfArrays[0], arrayOfArrays[1]);

document.getElementById('output').innerHTML = result.join(', ');
<div id="output"></div>

答案 1 :(得分:2)

请参阅下面的解决方案。我希望我能正确理解你的要求。您可以在下面的JSFiddle页面上看到输出。适用于任意数量的子阵列。

工作预览(3个子阵列):https://jsfiddle.net/gc90hsr3/

工作预览(4个子阵列):https://jsfiddle.net/gc90hsr3/3

function combine(arrays) {
    var first = arrays[0];
    var others = arrays.slice(0);
    others.splice(0, 1);
    
    var result = [];
    
    for(var i = 0; i < first.length; i++) {
        for(var j = 0; j < others.length; j++) {
            for(var k = 0; k < others[j].length; k++) {
                var str = first[i] + others[j][k];
                result.push(str);
            }
        }
    }
    
    return result;
    
};


var arrayOfArrays = [['apple', 'banana'], ['carrot', 'leek'], ['orange', 'pineapple']];
var combined = combine(arrayOfArrays);

document.getElementById('input').innerHTML = JSON.stringify(arrayOfArrays);
document.getElementById('output').innerHTML = combined;
<p><strong>Input: </strong><span id="input"></span></p>
<p><strong>Output: </strong><span id="output"></span></p>

答案 2 :(得分:1)

Sukima写了一个很好的答案,但它只适用于2个子阵列。您可以使用他的combiner作为帮助来实现您的目标:

    function combiner(base, subject) {
      return base.reduce(function(memo, baseValue) {
        subject.forEach(function(subjectValue) {
          memo.push(baseValue + subjectValue);
        });
        return memo;
      }, []);
    }

    function combine(array){
      var first = array[0];
      var others = array.slice(1);
      if (others.length == 1) return combiner(array[0],others[0]);
      return combiner(array[0],combine(others));
    }

    var arrayOfArrays = [['apple', 'banana'], ['carrot', 'leek'], ['orange', 'pineapple']];
    var combined = combine(arrayOfArrays);
    
    document.getElementById('output').innerHTML = combined;
<div id="output"></div>

答案 3 :(得分:0)

如果我在第二次尝试时了解您的要求,请参阅下面的工作解决方案。该解决方案适用于任意数量的子阵列和每个子阵列内的任意数量的元素。

本质上,关键是每个子数组都有它自己的独立指针,可以递增指向下一个字符串值,也可以重置为0,以便再次抓取所有值。下一个循环,但是使用前一个子数组中的字符串作为基础。

希望这会有所帮助,希望我终于正确地理解了你想要的东西:)

注意:连字符当然可以轻松删除。

JSFiddle:https://jsfiddle.net/L1vohz2e/

&#13;
&#13;
function combine(arrays) {
  var first = arrays[0];
  var source = arrays.slice(0); // Source = sub-arrays after first
  source.splice(0, 1);

  var result = [];

  for(var i = 0; i < first.length; i++) { // Every first sub-array element
    
    var pointers = {}; // Sub-array element pointers
    for(var p = 0; p < source.length; p++) {
      pointers[p] = 0;
    };
    var parentPointer = source.length-1; // Pointer for parent array, pointing to a sub-array (starting with last)

    while(parentPointer > -1) {
      var str = '';
      var j;
      for(j = 0; j < source.length; j++) { // Every sub-array
        str = str + '-' + source[j][pointers[j]]; // Grab strings that pointers are currently pointing at
      }
      result.push(first[i] + str); // Add line item to results array
      str = '';

      var k;
      var done = true;
      
      for(k = source.length-1; k > -1; k--) { // Every sub-array pointer starting at the end (going backwards)
        if(pointers[k] < source[k].length-1) { // If pointer not EOF (end of file), point to the next element
          pointers[k]++;
          parentPointer = k; // This pointer (sub-array) is the closest to the right that has strings not yet grabbed
          done = false; // We're not done, more strings to grab
          break;
        }
      }
      if(done) break; // Or, every pointer is pointing to the end of its sub-array (EOF), then we've grabbed everything
      for(var l = parentPointer+1; l < source.length; l++) { // If not done, reset all pointers in front of parentPointer set above
        pointers[l] = 0;
      }
    }

  }

  return result;
};



var arrayOfArrays = [['apple', 'banana'], ['carrot', 'leek'], ['orange', 'pineapple'], ['kiwi', 'grape']];
var combined = combine(arrayOfArrays);

var output = '';
for(var c in combined) {
  output = output + '<li>' + combined[c] + '</li>';
}

document.getElementById('input').innerHTML = JSON.stringify(arrayOfArrays);
document.getElementById('output').innerHTML = output;
&#13;
<p><strong>Input: </strong><span id="input"></span></p>
<p><strong>Output: </strong></p>
<ul id="output"></ul>
&#13;
&#13;
&#13;