【问题标题】:Generate all possible objects from a list of constraints [duplicate]从约束列表中生成所有可能的对象[重复]
【发布时间】:2017-10-13 18:22:36
【问题描述】:

我正在尝试从约束哈希生成所有可能的对象。

假设约束是:

{
    key1: [ 'possible value1' , 'possible value2' ],
    key2: [ 2, 4, 7, 1],
    ...
}

我想产生所有可能的对象:

{ key1: 'possible value1', key2: 2 }

{ key1: 'possible value1', key2: 4 }

...

谁能指出我正确的方向?

谢谢!

【问题讨论】:

标签: javascript algorithm


【解决方案1】:

var options = {
        key1: [ 'possible value1' , 'possible value2'],
        key2: [ 2, 4, 7, 1],
        key3: ['TEST1', 'TEST2']
};

function getCombinations(options, optionIndex, results, current) {
    var allKeys = Object.keys(options);
    var optionKey = allKeys[optionIndex];

    var vals = options[optionKey];

    for (var i = 0; i < vals.length; i++) {
        current[optionKey] = vals[i];

        if (optionIndex + 1 < allKeys.length) {
            getCombinations(options, optionIndex + 1, results, current);
        } else {
            var res = JSON.parse(JSON.stringify(current));
            results.push(res);
        }
    }

    return results;
}

var results = getCombinations(options, 0, [], {});

document.body.innerHTML = JSON.stringify(results);

【讨论】:

    【解决方案2】:

    let constraints = {
      key1: ['possible value1' , 'possible value2'],
      key2: [2, 4, 7, 1],
      key3: ["foo", "bar"],
    };
    
    let result = Object.keys(constraints).reduce(
      (acc, key) =>
        acc.map(a1 =>
          constraints[key].map(a2 =>
            a1.concat([a2])
          )
        ).reduce((e1, e2) => e1.concat(e2)),
      [[]]
    );
    
    console.log(JSON.stringify(result));

    首先,如果第一个包含数组(由一组约束生成的所有数组),第二个包含单个元素(一个新约束),我们首先要确保我们知道如何将两个数组的所有元素串联起来。 (例如[["possible value1"], ["possible value2"][1, 2])。我们映射一个数组,映射另一个数组,然后将它们粘在一起(a1a2 映射,a1.concat([a2]))。嵌套的map 将生成一个两级数组,因此我们只需连接单级(内部reduce)中的所有数组。

    请注意,如果我们将一个空数组连接到一个数组,则该数组是不变的;因此,我们可以引入另一个约束,一个空约束:[]。如果我们将与此约束对应的所有数组[[]]["possible value1", "possible value2"] 组合在一起,我们仍然得到相同的集合。这是我们外部reduce 的起始值:从这个“空元素”开始,我们可以像上面描述的那样连接其他约束。

    编辑:变得更漂亮:

    let constraints = {
      key1: ['possible value1' , 'possible value2'],
      key2: [2, 4, 7, 1],
      key3: ["foo", "bar"],
    };
    
    const unconstrainedPossibilities = [[]];
    
    const flatten = array => array.reduce((a1, a2) => a1.concat(a2));
    
    const addConstraint = (possibilities, constraint) =>
      flatten(
        possibilities.map(possibility =>
          constraint.map(constraintValue =>
            possibility.concat([constraintValue])
          )
        )
      );
    
    const possibilitiesFor = constraints =>
      constraints.reduce(
        (possibilities, constraint) => addConstraint(possibilities, constraint),
        unconstrainedPossibilities
      );
    
    let possibilities = possibilitiesFor(Object.values(constraints));
    console.log(JSON.stringify(possibilities));

    【讨论】:

      【解决方案3】:

      我知道有更优雅的方法可以做到这一点,但我想提出一个不需要太多思考的算法,所以,我的想法只是使用一个基本的 while 循环,其中每次迭代循环创建下一个组合并将其粘贴到输出数组中。

      我首先创建一个keys 数组,其中包含{k: "key1", index: 0, length: 2} 形式的每个键的对象 - 基本上是为了跟踪该键我们在其数组中达到的索引,以及它的数组的长度.然后while 循环的第一行使用.reduce() 使用每个键的当前索引中的值构建一个对象,然后使用for 循环移动到下一个组合。当它到达组合的末尾时,它会跳出while 循环。

      const constraints = {
        key1: ['pv1', 'pv2', 'pv3', 'pv4'],
        key2: [2, 4, 7, 1],
        key3: ['a', 'b'],
        key4: [10, 20, 30]
      }
      
      const output = []
      
      const keys = Object.keys(constraints)
        .map(k => ({ k: k, index: 0, length: constraints[k].length }))
      
      process: while (true) {
        output.push(keys.reduce((a, c) => {
          a[c.k] = constraints[c.k][c.index];
          return a;
        }, {}))
      
        for (let i = keys.length - 1; i >= 0; i--) {
          keys[i].index++
          if (keys[i].index < keys[i].length) break
          if (i === 0) break process
          keys[i].index = 0
        }
      }
      
      console.log(JSON.stringify(output))

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-08
        • 2018-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        • 1970-01-01
        相关资源
        最近更新 更多