Javascript对象或数组的排列组合

Permutation and combination of Javascript Object or Array

我有一个这样的 javascript 对象:

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

我想用所有可能的组合生成它:

{
    [{"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}]
    
}

是的,这个答案是 this earlier post on generating a Cartesian product from arrays 的应用,因此可以看作是重复的。但也许实际的实现仍然在这里增加了一些价值:

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)));

通用解决方案需要嵌套在笛卡尔积中的排列,该排列允许具有不同 属性 counts/names 的对象。这里使用 Permutations in JavaScript? and Cartesian product of multiple arrays in JavaScript 的答案,然后将结果映射到原始输入的 Object.keys

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 
 */
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 
 */
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>

具有不同 属性 计数的示例

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 
 */
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 
 */
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>