Home > front end >  Permutation and combination of Javascript Object or Array
Permutation and combination of Javascript Object or Array

Time:04-08

I have a javascript object like this:

[{"w": 202, "h": 302}, { "w": 402, "h": 502}, {"w": 802, "h": 702}]

and I want to generate it like this with all the possible combination:

{
    [{"w": 302, "h": 202}, { "w": 402, "h": 502}, {"w": 802, "h": 702}],
    [{"w": 202, "h": 302}, { "w": 502, "h": 402}, {"w": 802, "h": 702}],
    [{"w": 202, "h": 302}, { "w": 402, "h": 502}, {"w": 702, "h": 802}],
    [{"w": 302, "h": 202}, { "w": 502, "h": 402}, {"w": 802, "h": 702}],
    [{"w": 202, "h": 302}, { "w": 502, "h": 402}, {"w": 702, "h": 802}],
    [{"w": 302, "h": 202}, { "w": 402, "h": 502}, {"w": 702, "h": 802}],
    [{"w": 302, "h": 202}, { "w": 502, "h": 402}, {"w": 702, "h": 802}]
    
}

CodePudding user response:

Yes, this answer is an application of this earlier post on generating a Cartesian product from arrays and can therefore be seen as a duplicate. But maybe the actual implementation still adds some value here:

const da=[{"w": 202, "h": 302}, { "w": 402, "h": 502}, {"w": 802, "h": 702}];
  
function cart(da){
 const arr=da.map(o=>[o,{w:o.h,h:o.w}]);
 return arr.reduce((a0, a) => a0.flatMap(e0 => a.map(e => [e0, e].flat())))
}
  
console.log(JSON.stringify(cart(da)));

CodePudding user response:

A generic solution requires a permutation nested in a cartesian product which allows for objects with varying property counts/names. Here using answers from Permutations in JavaScript? and Cartesian product of multiple arrays in JavaScript and them mapping the result against the Object.keys of the original input.

const input = [{ "w": 202, "h": 302 }, { "w": 402, "h": 502 }, { "w": 802, "h": 702 }];

const result = cartesian(
    ...input.map(o =>
        permute(Object.values(o))
            .map(v => [v])
    ))
    .map(vs =>
        vs.map((v, i) =>
            Object.fromEntries(
                Object.keys(input[i]).map((k, j) => [k, v[j]]))
        )
    );

// log
result.forEach(r => console.log(JSON.stringify(r)));
<script>
/**
 * @see https://stackoverflow.com/questions/9960908/permutations-in-javascript
 */
function permute(permutation) {
    var length = permutation.length,
        result = [permutation.slice()],
        c = new Array(length).fill(0),
        i = 1, k, p;

    while (i < length) {
        if (c[i] < i) {
            k = i % 2 && c[i];
            p = permutation[i];
            permutation[i] = permutation[k];
            permutation[k] = p;
              c[i];
            i = 1;
            result.push(permutation.slice());
        } else {
            c[i] = 0;
              i;
        }
    }
    return result;
}

/**
 * @see https://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript
 */
let f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
let cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;
</script>

Example with varying property counts

const input = [{ "w": 202}, { "w": 402, "h": 502, "x": 'extra prop' }, { "w": 802, "h": 702 }];

const result = cartesian(
    ...input.map(o => permute(Object.values(o)).map(v => [v])))
    .map(vs => vs.map((v, i) =>
        Object.fromEntries(
            Object.keys(input[i]).map((k, j) => [k, v[j]]))));

// log
result.forEach(r => console.log(JSON.stringify(r)));
<script>
/**
 * @see https://stackoverflow.com/questions/9960908/permutations-in-javascript
 */
function permute(permutation) {
    var length = permutation.length,
        result = [permutation.slice()],
        c = new Array(length).fill(0),
        i = 1, k, p;

    while (i < length) {
        if (c[i] < i) {
            k = i % 2 && c[i];
            p = permutation[i];
            permutation[i] = permutation[k];
            permutation[k] = p;
              c[i];
            i = 1;
            result.push(permutation.slice());
        } else {
            c[i] = 0;
              i;
        }
    }
    return result;
}

/**
 * @see https://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript
 */
let f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
let cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;
</script>

  • Related