3

I currently have an Javascript array of unknown length, containing arrays (of unknown length) of strings. I'm looking for a way to find every possible combination, using one string from every second level array. Note: order of the strings do not matter. That is, for:

[
    [
        'a',
        'b'
    ],
    [
        'c',
        'd'
    ]
]

I would like to return:

[
    'ac',
    'ad',
    'bc',
    'bd'
]

or, given:

[
    [
        'a',
        'b'
    ],
    [
        '1'
    ],
    [
        'i',
        'j',
        'k',
    ]
]

I would like to return:

[
    'a1i',
    'a1j',
    'a1k',
    'b1i',
    'b1j',
    'b1k',
]

I feel like the answer lies in a recursive function, however I cannot seem to get it work (the variable scoping keeps getting confusing and it just falls flat).

Instead, I've tried another way of creating a results array, looping through each subarray and placing each string in the results in such a way that each possible combination is created:

function getArrayStrings(allTerms){

    // get total number of possible combinations
    var numberOfElements = 1;

    $.each(allTerms, function(index, element){
        numberOfElements *= element.length;
    });


    // create array of results
    var result = [];

    for(i = 0; i < numberOfElements; i ++){
        result[i] = '';
    }

    // instantiate variables that will be used in loop
    var elementToUse = 0;
    var currentLength = 1;
    var prevLength = 1;

    // for each array, loop through values and add them to the relevant result element
    $.each(allTerms, function(index, array){    

        // find length of current array
        currentLength = array.length;
        elementToUse = 0;

        // for each of the elements in the results array
        for(i = 0; i < numberOfElements; i ++){

            // change the element to use if you've looped through the previous length (but not if it's first result
            if(i !== 0 && i % prevLength === 0){
                elementToUse ++;
            }

            // return to using the first element if you've reached the last element in the sub array
            if(elementToUse % currentLength === 0){
                elementToUse = 0;
            }

            result[i] += '.' + array[elementToUse];

        }

        prevLength = array.length * prevLength;

    });

    console.log(result.join(''));

    return result.join('');

}

This does work, however I wondered whether anyone knew of a simpler function; I feel like this is something that would have some Javascript (or jQuery) function in there already, but I can't find it.

Has anyone come across a challenge like this before? And, if so, how did you approach it?

3 Answers 3

1

Simple recursion:

    var a = [ [ 'a', 'b' ],
              [ '1' ],
              [ 'i', 'j', 'k' ]
    ];

    function combo( arr, i, j ) {
        if (i===j-1) return arr[i];   
        var res = [];
        arr[i].forEach( function(a) {
            combo( arr, i+1, j ).forEach( function(b) {
                res.push(a+b);
            });
        });
        return res;
    }

    console.log( combo(a, 0, a.length) );

http://jsfiddle.net/zpg04kso/1/

Sign up to request clarification or add additional context in comments.

1 Comment

Great answers, all three. Chose this one because it showed me how to do it using recursion - was interested in how to do this.
0

I took advantage of the fact that you can combine the sub arrays in pairs. It seems a little more straight forward to me.

var input = [
    ['a','b'],
    ['1', '2','3','4'],
    ['i','j','k']
];

function getArrayStrings(input) {    
    function combine(arr1, arr2) {
        var output = [];
        for (var i=0;i<arr1.length;i++) {
            for(var j=0;j<arr2.length;j++) {
                 output.push(arr1[i] + arr2[j]);
            }
        }
        return output;
    }

    var output = [];
    for(var i=0;i<input.length;i++) {
        if (i==0) output = input[i];
        else output = combine(output, input[i]);
    }

    return output;
}

var output = getArrayStrings(input);
console.log(output);

http://jsfiddle.net/blaird/kcytLv1r/

1 Comment

Thanks for your answer. Great thinking, really appreciated :)
0

This works..

var a = [['a','b'], ['1'],['i','j','k']],
        b = [];


function cat(a1,a2){
    var a = []
            l = undefined;

    while (a2.length > 0){
        l = a2.shift();
        a1.forEach(function(ele,idx,arr){
            a.push(ele + l)
        })
    }
    return a;
}

function merge(arr){
    if (arr.length == 1){
        return arr.shift()
    } else {
        var a1 = arr.shift()
        return cat(a1,merge(arr))
    }
}


var b = merge(a);
console.log(b)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.