web-dev-qa-db-ja.com

Javascript-単一の配列内の要素のすべての組み合わせを(ペアで)生成する

配列内の要素のすべての可能な組み合わせを生成する方法について、いくつかの同様の質問を見てきました。しかし、組み合わせpairsのみを出力するアルゴリズムを作成する方法を見つけるのは非常に困難です。どんな提案でも大歓迎です!

次の配列(N要素)から開始します。

var array = ["Apple", "banana", "lemon", "mango"];

そして、次の結果を取得します。

var result = [
   "Apple banana"
   "Apple lemon"
   "Apple mango"
   "banana lemon"
   "banana mango"
   "lemon mango"
];

私は次のアプローチを試していましたが、これはすべての可能な組み合わせになり、代わりに組み合わせのペアのみになります。

var letters = splSentences;
var combi = [];
var temp= "";
var letLen = Math.pow(2, letters.length);

for (var i = 0; i < letLen ; i++){
    temp= "";
    for (var j=0;j<letters.length;j++) {
        if ((i & Math.pow(2,j))){ 
            temp += letters[j]+ " "
        }
    }
    if (temp !== "") {
        combi.Push(temp);
    }
}
15
dhdz

簡単な方法は、2番目のループで最初のi要素をスキップする配列に対してdouble forループを実行することです。

let array = ["Apple", "banana", "lemon", "mango"];
let results = [];

// Since you only want pairs, there's no reason
// to iterate over the last element directly
for (let i = 0; i < array.length - 1; i++) {
  // This is where you'll capture that last value
  for (let j = i + 1; j < array.length; j++) {
    results.Push(`${array[i]} ${array[j]}`);
  }
}

console.log(results);

ES5で書き直されました:

var array = ["Apple", "banana", "lemon", "mango"];
var results = [];

// Since you only want pairs, there's no reason
// to iterate over the last element directly
for (var i = 0; i < array.length - 1; i++) {
  // This is where you'll capture that last value
  for (var j = i + 1; j < array.length; j++) {
    results.Push(array[i] + ' ' + array[j]);
  }
}

console.log(results);
18
Mike Cluck

2つの機能プログラミング ES6ソリューションがあります。

var array = ["Apple", "banana", "lemon", "mango"];

var result = array.reduce( (acc, v, i) =>
    acc.concat(array.slice(i+1).map( w => v + ' ' + w )),
[]);

console.log(result);

または:

var array = ["Apple", "banana", "lemon", "mango"];

var result = [].concat(...array.map( 
    (v, i) => array.slice(i+1).map( w => v + ' ' + w ))
);

console.log(result);
14
trincot

解決策は見つかりましたが、ここでは一般的な場合のサイズn of m (m>n)要素を見つけるための一般的なアルゴリズムを投稿します。あなたの場合、n=2およびm=4

const result = [];
result.length = 2; //n=2

function combine(input, len, start) {
  if(len === 0) {
    console.log( result.join(" ") ); //process here the result
    return;
  }
  for (var i = start; i <= input.length - len; i++) {
    result[result.length - len] = input[i];
    combine(input, len-1, i+1 );
  }
}

const array = ["Apple", "banana", "lemon", "mango"];    
combine( array, result.length, 0);
9
nhnghia

mapおよびflatMapを使用すると、次のことができます(flatMapchromeおよびfirefox でのみサポートされます)

var array = ["Apple", "banana", "lemon", "mango"]
array.flatMap(x => array.map(y => x !== y ? x + ' ' + y : null)).filter(x => x)
1
Peter

配列内の要素の組み合わせの生成は、数値システムでのカウントによく似ています。ここで、基数は配列内の要素の数です(欠落している先行ゼロを考慮した場合)。

これにより、配列へのすべてのインデックスが得られます(連結されます)。

_arr = ["Apple", "banana", "lemon", "mango"]
base = arr.length

idx = [...Array(Math.pow(base, base)).keys()].map(x => x.toString(base))
_

2つのペアのみに関心があるため、それに応じて範囲を制限します。

_range = (from, to) = [...Array(to).keys()].map(el => el + from)
indices = range => range.map(x => x.toString(base).padStart(2,"0"))

indices( range( 0, Math.pow(base, 2))) // range starts at 0, single digits are zero-padded.
_

あとは、インデックスを値にマップするだけです。

要素をそれ自体とペアにしたくないし、順序は関係ないので、最終結果にマッピングする前に、それらを削除する必要があります。

_const range = (from, to) => [...Array(to).keys()].map(el => el + from)
const combinations = arr => {
  const base = arr.length
  return range(0, Math.pow(base, 2))
    .map(x => x.toString(base).padStart(2, "0"))
    .filter(i => !i.match(/(\d)\1/) && i === i.split('').sort().join(''))
    .map(i => arr[i[0]] + " " + arr[i[1]])
}

console.log(combinations(["Apple", "banana", "lemon", "mango"]))_

10個以上の要素がある場合、toString()はインデックスの文字を返します。また、これは最大36個の要素でのみ機能します。

0
Kolja

これを試してください: https://jsfiddle.net/e2dLa9v6/

var array = ["Apple", "banana", "lemon", "mango"];
var result = [];

for(var i=0;i<array.length-1;i++){
    for(var j=i+1;j<array.length;j++){
    result.Push(array[i]+" "+array[j]);
  }
}
for(var i=0;i<result.length;i++){
    alert(result[i]);
}
0
Konstantinos