Я действительно избил это в землю. Как и ожидалось, ответ @Louis Durand двух вложенных циклов был самым быстрым в массиве, содержащем 100 строк (около 4 мс на моей машине). Это показывает, что вложенная петля, вероятно, является вашим лучшим выбором в этой ситуации.
Второй самый быстрый - это рекурсивное решение, которое делало то же самое около 7-8 мс.
В-третьих, это ответ @Redu, который за такую ??же задачу составлял около 12-15 мс. Я подозреваю, что его реализация медленнее, потому что он использует метод slice в своем algo для обновления массива (другие ответы только увеличивают индекс, оставляя неизменный входной массив, что намного быстрее). Также эта реализация приводит к тому, что несколько копий входного массива хранятся в памяти (каждый раз, когда вызываемая функция создает новый входной массив из исходного массива, из которого он удаляет первый элемент). Это также может повлиять на производительность.
Поэтому, чтобы ответить на ваш вопрос: нет. Я не думаю, что есть гораздо лучший подход к тому, что вы делаете, кроме как конкатенация на строку и ответы на печать в самом конце (что предложил Луис).
var arr = [];
for (var i = 0; i< 100; i++){
arr.push(i+"");
}
/*
console.time("test0");
test0();
function test0() {
var s = "";
for (var i=0; i<arr.length-1;i++) {
for (var j=i+1; j<arr.length;j++) {
s += arr[i] + " " + arr[j]+" ; ";
}
s += "
";
}
console.log(s);
}
console.timeEnd("test0");
*/
console.time("test1");
test1();
function test1() {
var output = [];
getCombos(0, 0, [], 2);
console.log(JSON.stringify(output));
function getCombos(index, depth, tmp, k){
if(depth < k){
for(var i = index; i<arr.length; i++){
var tmp1 = [arr[i]];
Array.prototype.push.apply(tmp1, tmp);
getCombos(i+1, depth+1,tmp1, k);
}
}else{
output.push(tmp);
}
}
}
console.timeEnd("test1");
/*
console.time("test2");
test2();
function test2(){
Array.prototype.combinations = function(n){
return this.reduce((p,c,i,a) => (Array.prototype.push.apply(p,n > 1 ? a.slice(i+1).combinations(n-1).map(e => (e.push(c),e))
: [[c]]),p),[]);
};
console.log(JSON.stringify(arr.combinations(2)));
}
console.timeEnd("test2");*/
Вот рекурсивное решение, которое не решает проблему сложности времени, но это еще один способ рассмотрения. Дополнительным преимуществом является то, что вы можете обобщить его на любой k, чтобы не застревать в поиске только двух букв. Также вы объявляете только один цикл (хотя более чем одна его копия будет существовать в вашем стеке вызовов)
var arr = ["a", "b", "c", "d", "e"];
var output = "";
getCombos(0, 0, [], 2);
console.log(output);
function getCombos(index, depth, tmp, k){
if(depth < k){
for(var i = index; i<arr.length; i++){
var tmp1 = [...tmp, arr[i]];
getCombos(i+1, depth+1,tmp1, k);
}
}else{
output += tmp.toString() + ";";
}
}