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

时间:2023-01-20 20:30:35

I have the following two arrays within a single array:

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

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

I want to concatenate all options in the first array with all options in the second array. So I would have the following 4 results:

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

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

The solution should work with any number of sub-arrays. So we could have an array of fruits, vegetables and flowers, each containing n number of items. Each result must also contain one word from each sub-array. So if there are 3 sub-arrays, all results will contain 3 words.

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

Example with 3 arrays:

3个数组的示例:

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

I have come up with the following but it only seems to produce ['applecarrot', 'appleleek'].

我想出了以下内容,但它似乎只能产生['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 个解决方案

#1


3  

There isn't any built in way you going to have to make your own. Fist off there isn't any need to have an array within an array. Your only dealing with two options really (base array and one or more modifier arrays) So you could construct a function to iterate over them:

没有任何内置的方法你必须自己制作。 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>

#2


2  

See below for my solution. I hope I've understood your requirements correctly. You can see the output on the JSFiddle page below. Works with any number of sub-arrays.

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

Working Preview (3 sub-arrays): https://jsfiddle.net/gc90hsr3/

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

Working Preview (4 sub-arrays): https://jsfiddle.net/gc90hsr3/3

工作预览(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>

#3


1  

Sukima wrote an excellent answer but it only works for 2 sub-arrays. You can use his combiner as a helper to achieve your goal:

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

    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>

#4


0  

See below for a working solution, if I've understood your requirements on my second attempt. This solution will work with any number of sub-arrays and any number of elements inside each sub-array.

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

Essentially, the key is for each sub-array to have it's own independent pointer, that is either incremented to point to the next string value, or reset back to 0 for all values to be grabbed again on the next cycle, but with a string from a preceding sub-array as the base.

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

Hope this helps, and hopefully I've finally correctly understood what you want :)

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

Note: The hyphens are of course easily removable.

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

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

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;
<p><strong>Input: </strong><span id="input"></span></p>
<p><strong>Output: </strong></p>
<ul id="output"></ul>

#1


3  

There isn't any built in way you going to have to make your own. Fist off there isn't any need to have an array within an array. Your only dealing with two options really (base array and one or more modifier arrays) So you could construct a function to iterate over them:

没有任何内置的方法你必须自己制作。 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>

#2


2  

See below for my solution. I hope I've understood your requirements correctly. You can see the output on the JSFiddle page below. Works with any number of sub-arrays.

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

Working Preview (3 sub-arrays): https://jsfiddle.net/gc90hsr3/

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

Working Preview (4 sub-arrays): https://jsfiddle.net/gc90hsr3/3

工作预览(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>

#3


1  

Sukima wrote an excellent answer but it only works for 2 sub-arrays. You can use his combiner as a helper to achieve your goal:

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

    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>

#4


0  

See below for a working solution, if I've understood your requirements on my second attempt. This solution will work with any number of sub-arrays and any number of elements inside each sub-array.

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

Essentially, the key is for each sub-array to have it's own independent pointer, that is either incremented to point to the next string value, or reset back to 0 for all values to be grabbed again on the next cycle, but with a string from a preceding sub-array as the base.

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

Hope this helps, and hopefully I've finally correctly understood what you want :)

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

Note: The hyphens are of course easily removable.

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

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

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;
<p><strong>Input: </strong><span id="input"></span></p>
<p><strong>Output: </strong></p>
<ul id="output"></ul>