Paul
Paul

Reputation: 75

Loop through values in arrays in an array. Output all combinations

I have an object. I want to loop through one of it's properties: itself an array of arrays which contain values. For every one of those values, I want to output an array containing a representative value from each of the child arrays, such that every possible combination of values will be output. Where there are more than one value in a child array, a max of 1 value at a time should be allowed. It's at this point that I think it should 'jump on' to the next one (and do the same for all others) but I'm not sure how. The results should look like this:

RABBIT: GREY, FURRY, BOUNCES, CUTE

RABBIT: WHITE, FURRY, BOUNCES, CUTE

RABBIT: RED, FURRY, BOUNCES, CUTE

RABBIT: GREY, FURRY, SCAMPERS, CUTE

RABBIT: WHITE, FURRY, SCAMPERS, CUTE

RABBIT: RED, FURRY, SCAMPERS, CUTE

The array (and it's child arrays) will have unknown lengths, so I've used the for loop. Here is the code so far:

window.onload = function (){
var myObject = {
        name: 'RABBIT',
        arrayOfValues : [
            ['GREY','WHITE','RED'],
            ['FURRY'],
            ['BOUNCES', 'SCAMPERS'],
            ['CUTE']
        ]
    };

var results = [];
for (i=0;i<myObject.arrayOfValues.length;i++){
    for (j=0; j<myObject.arrayOfValues[i].length;j++){
        if(myObject.arrayOfValues[i].length>1) {
            var currentProperty = myObject.arrayOfValues[i][j];
            myFunc();
        }
        else {
            var currentProperty = myObject.arrayOfValues[i][0];
            myFunc();
        };
    };
};

function myFunc(){
    results = results.concat(currentProperty);
    if (results.length == myObject.arrayOfValues.length){
    var finalResults = myObject.name + ': ' + results
    console.log(finalResults);
    };
};
};

PS - The form of the data is not set in stone, I just used an object for convenience.

Thanks, Paul

Upvotes: 1

Views: 788

Answers (2)

Selfish
Selfish

Reputation: 6200

Recursion is the native solution here:

// Object as described by question:
var myObject = {
    name: 'RABBIT',
    arrayOfValues: [
        ['GREY', 'WHITE', 'RED'],
        ['FURRY'],
        ['BOUNCES', 'SCAMPERS'],
        ['CUTE']
    ]
};

function permutations(arrays, current_array, idx, results) {
    // Init head and results in case this is the first iteration:
    idx = idx || 0;
    results = results || [];
    current_array = current_array || [];
    // If there's nothing more to add:
    if (arrays.length == idx) {
        results.push(current_array);
        return;
    }
    // Otherwise, iterate current level and concat values, while calling next level:
    arrays[idx].forEach(function(subArrayItem) {
        permutations(arrays, current_array.concat(subArrayItem), idx + 1, results)
    });
    return results;
}

The function above will return a set of arrays having all combinations, next is a helper function for printing:

// Helper method to print resulting arrays:
function print(obj) {
    var separator = "\n"
    var prefix = obj.name + ": ";
    // Joins the resulting sets with the prefix, and returns printable string:
    return prefix + permutations(obj.arrayOfValues).join(separator + prefix)
}

console.log(print(myObject));

Upvotes: 2

Robin James Kerrison
Robin James Kerrison

Reputation: 1767

You can make a recursive function call with an increasing index parameter, as well as a string to which you append the new part of the string and return.

var arrayOfArrays = [
  ['big', 'red'],
  ['red', 'yellow', 'blue'],
  ['dog', 'cat']
];

var strings = [];

function eachStep(string_so_far, array_index) {
  if (array_index < arrayOfArrays.length) {
    for (var i = 0; i < arrayOfArrays[array_index].length; i++) {
      var string_for_this_step = string_so_far + arrayOfArrays[array_index][i] + " ";
      var string_returned = eachStep(string_for_this_step, array_index+1);
      if (string_returned !== "") {
        strings.push(string_returned);
      }
    }
    return "";
  } else {
    return string_so_far;
  }
}

eachStep("", 0);

console.log(strings);

Upvotes: 4

Related Questions