2017-05-15 9 views
1

制約ハッシュからすべてのオブジェクトを生成しようとしています。制約リストからすべてのオブジェクトを生成する

のは制約があるとしましょう:

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

そして、私はすべての可能なオブジェクトを生成します:

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

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

... 

誰もが正しい方向に私を指すことができますか?

ありがとうございました!

+0

見る(http://stackoverflow.com/q/15298912/1048572)[M元素と、N個のアレイからの組み合わせの生成]。あなたのケースでは、それらはオブジェクトのプロパティですが、違いはありません – Bergi

答えて

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

1

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

まず最初はいくつかによって生成アレイ(すべてのアレイが含まれている場合、我々は、我々は2つの配列の要素をすべて連結を作る方法を知っていることを確認してください制約のセット)と第2の単一の要素(新しい制約)。 (例えば、[["possible value1"], ["possible value2"]および[1, 2])。 1つの配列をマップし、別の配列をマップしてから貼り付けます(a1a2のマップ、a1.concat([a2]))。入れ子になったmapは2レベルの配列を生成するので、すべての配列を1つのレベル(内部reduce)から連結します。

空の配列を配列に連結すると、配列は変更されません。したがって、もう1つの制約、空のもの、[]を導入することができます。この制約に対応するすべての配列、[[]]["possible value1", "possible value2"]を組み合わせると、同じセットが得られます。これは外部reduceの開始値です。この「null要素」から始めて、前述のように他の制約を連結することができます。

EDIT:きれいに作られた:

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

0

私はこれを行うにはよりエレガントな方法があります知っているが、私は本当に多くの思考を伴わなかったアルゴリズムを思い付くしたいですだから、私の考えはループの各繰り返しが次の組み合わせを作成し、それを出力配列に貼り付ける基本的なループを使用することだけでした。

{k: "key1", index: 0, length: 2}の形式で各キーのオブジェクトを含むkeys配列を作成することから始めます。基本的には、配列内のどのインデックスのキーか、その配列の長さを追跡します。次に、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))

関連する問題