生成多维对象的所有组合

时间:2018-10-26 11:30:35

标签: javascript algorithm object

问题

我想为一个类似模板的对象生成所有组合,该组合可以包含多个子级,其中一些将所需的输出定义为数组。这些孩子也可以生孩子(实际上没有限制)。

示例输入

const input = {
  a: [true, false],
  b: ['first', 'second'],
  c: {
    d: [true, false]
  }
};

示例输出

const output = [
  {
    a: true,
    b: 'first',
    c: {
      d: true
    }
  },
  {
    a: true,
    b: 'first',
    c: {
      d: false
    }
  },
  {
    a: true,
    b: 'second',
    c: {
      d: true
    }
  },
  {
    a: true,
    b: 'second',
    c: {
      d: false
    }
  },
  //...
]

问题

将输入转换为输出的JavaScript函数是什么?

尝试了什么?

我尝试从此问题中获取原始功能,使其更符合ES,但是在对象中有多个子代时,此功能不起作用。

function combinations(input, keyIndex = 0, current = {}, result = []) {
  const keys = Object.keys(input)
  const key = keys[keyIndex]
  const values = input[key]

  for (const index in values) {
    current[key] = values[index]

    if (keyIndex + 1 < keys.length) {
      combinations(input, keyIndex + 1, current, result)
    } else {
      result.push(JSON.parse(JSON.stringify(current)))
    }
  }

  return result;
}

1 个答案:

答案 0 :(得分:3)

如果具有对象的数组再次调用getCartesian并构建新的对象,则可以采用递归函数来分离所有键/值对,并通过迭代值来构建新的笛卡尔积。

这同样适用于嵌套对象。

function getCartesian(object) {
    return Object.entries(object).reduce((r, [k, v]) => {
        var temp = [];
        r.forEach(s =>
            (Array.isArray(v) ? v : [v]).forEach(w =>
                (w && typeof w === 'object' ? getCartesian(w) : [w]).forEach(x =>
                    temp.push(Object.assign({}, s, { [k]: x }))
                )
            )
        );
        return temp;
    }, [{}]);
}

var input = { a: [true, false], b: ['first', 'second'], c: { d: [true, false] } },
    cartesian = getCartesian(input);

console.log(cartesian);
.as-console-wrapper { max-height: 100% !important; top: 0; }