Javascript - создание всех комбинаций элементов в одном массиве (попарно)
Я видел несколько похожих вопросов о том, как создавать все возможные комбинации элементов в массиве. Но мне очень трудно понять, как написать алгоритм, который будет выводить только пары комбинаций. Любые предложения были бы оценены очень высоко!
Начиная со следующего массива (с 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);
}
}
Ответы
Ответ 1
Простым способом было бы сделать двойной цикл для массива, где вы пропускаете первые элементы i
во втором цикле.
let array = ["apple", "banana", "lemon", "mango"];
let results = [];
// Since you only want pairs, there 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);
Ответ 2
Вот некоторые решения для функционального программирования:
Использование EcmaScript2019 flatMap
:
var array = ["apple", "banana", "lemon", "mango"];
var result = array.flatMap(
(v, i) => array.slice(i+1).map( w => v + ' ' + w )
);
console.log(result);
Ответ 3
Хотя решения были найдены, я размещаю здесь алгоритм для общего случая, чтобы найти все комбинации размером n
из 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);
Ответ 4
Используя map
и flatMap
можно сделать следующее (flatMap
поддерживается только в Chrome и Firefox)
var array = ["apple", "banana", "lemon", "mango"]
array.flatMap(x => array.map(y => x !== y ? x + ' ' + y : null)).filter(x => x)
Ответ 5
Попробуйте следующее: 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]);
}
Ответ 6
Генерация комбинаций элементов в массиве очень похожа на подсчет в системе счисления, где основание - это количество элементов в вашем массиве (если вы учитываете ведущие нули, которые будут отсутствовать).
Это дает вам все индексы для вашего массива (сцепленные):
arr = ["apple", "banana", "lemon", "mango"]
base = arr.length
idx = [...Array(Math.pow(base, base)).keys()].map(x => x.toString(base))
Вас интересуют только пары из двух, поэтому ограничьте диапазон соответствующим образом:
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"]))