2017-02-20 9 views
0

, поэтому я пытаюсь написать функцию, которая сохранит элементы, присутствующие в двух или более массивах, только если элементы произошли в двух или более массивах.Как сохранить элементы, присутствующие в двух или более массивах, и вернуть массив?

E.g., 
a = ["Amy", "Sheldon", "Raj"] 
b = ["Amy", "Penny", "Leonard"] 
c = ["Amy", "Penny", "Howard"] 

Результат должен быть [«Эми», «Пенни»], потому что их вхождения 2 или более.

Прямо сейчас у меня есть метод, который идет против каждого массива и сравнивается со всеми остальными массивами, что очень медленно. Я объединяю несколько массивов, и каждый массив может иметь до 10000 объектов.

Любые предложения?

+0

вам нужно сохранить порядок ли? (Если это так, гарантировано ли, что '[" A "," B "]', за которым следуют '[" B "," A "]' невозможно, или если у вас есть приоритет?) – Ryan

+0

Вам нужно будет перейти каждый массив. Рассмотрите возможность создания объекта, чьи ключи являются значениями и значениями, являются количеством раз, сколько раз возникает ключ. Затем создайте новый массив, где значения равны 2 или больше. – RobG

ответ

2

Вы можете перебирать массивы и создавать объект значений и сколько раз они встречаются, а затем перебирать результат для сбора значений, которые происходят дважды или более, например.

var a = ["Amy", "Sheldon", "Raj", "Raj"] 
 
var b = ["Amy", "Penny", "Leonard"] 
 
var c = ["Amy", "Penny", "Howard"] 
 

 
// Create object of value:count 
 
var counts = [a,b,c].reduce(function(acc, arr) { 
 

 
    // Remove duplicates from array 
 
    arr = arr.filter(function(value, i){ 
 
    return arr.indexOf(value) == i; 
 
    }); 
 
    
 
    // Add to and increment accumulator 
 
    arr.forEach(function(value) { 
 
    acc[value] = (acc[value] || 0) + 1; 
 
    }); 
 
    return acc; 
 
},Object.create(null)); 
 

 
// Create array of value where count > 1 
 
var result = Object.keys(counts).filter(function(key){ 
 
    return counts[key] > 1; 
 
}); 
 

 
console.log(result); // Amy, Penny 
 
        // Raj not included as only in 1 array

Если вы можете положиться на поддержку современных функций, то следующие могут подойти:

var a = ["Amy", "Sheldon", "Raj"]; 
 
var b = ["Amy", "Penny", "Leonard"]; 
 
var c = ["Amy", "Penny", "Howard"]; 
 

 

 
var counts = [a, b, c].reduce((acc, arr) => { 
 
    arr.filter(function(value, i){ 
 
    return arr.indexOf(value) == i; 
 
    }).forEach(value => acc[value] = (acc[value] || 0) + 1); 
 
    return acc; 
 
}, Object.create(null)); 
 

 
var result = Object.keys(counts).filter(key => counts[key] > 1); 
 

 
console.log(result);

Обратите внимание, что это не может сохранить порядок. Если вам нужен заказ, чтобы быть гарантированным, используйте Map вместо объекта для счет, так как он будет поддерживать порядок вставки.

Использование Object.create(null) означает, что аккумулятор не имеет свойств, отпадет потребность в hasOwnProperty испытания на:

acc[value] = (acc[value] || 0) + 1; 
+0

Они будут сообщать элементы, которые встречаются дважды или более в одном массиве ввода, но не в любом из других. –

+0

Я думаю, это должно быть хорошо, поскольку мы всегда можем объединить несколько массивов в один массив. У меня есть немного проблем с переписыванием вышеуказанного кода Javascript в TypeScript, любые подсказки? более конкретно, я не знаю строки после «return acc», «}, {});" должен быть какой тип в машинописном тексте. –

+0

@ torazaburo-хороший момент, позвольте мне исправить это ... – RobG