2013-04-26 19 views
21

otrzymuje dwie tablice nierównej długości:Oblicz przecięcia dwóch tablic w JavaScript

var arr1 = ["mike", "sue", "tom", "kathy", "henry"]; //arr1.length = 5 
var arr2 = ["howey", "jim", "sue", "jennifer", "kathy", "hank", "alex"]; //arr2.length = 7 

Jak mogę znaleźć wartości wspólne dla obu tablicach? W takim przypadku należy zwrócić: "sue" i "kathy".

+0

Czy chcesz, aby sue i kathy miały swoje wyniki w tej sprawie? – ggbranch

+0

Szukam znaleźć mecze, popraw. – Justin

Odpowiedz

15

Chcesz znaleźć przecięcie dwóch tablic?

Można użyć znaku podkreślenia intersection(). To da ci listę wartości obecnych w obu tablicach.

var commonValues = _.intersection(arr1, arr2); 

jsFiddle.

Jeśli nie chcesz korzystać z biblioteki, to byłoby trywialne do realizacji ...

var commonValues = arr1.filter(function(value) { 
            return arr2.indexOf(value) > -1; 
           }); 

jsFiddle.

Jeśli Array.prototype.filter() i Array.prototype.indexOf() nie są obsługiwane w swoich platformach docelowych ...

var commonValues = []; 
var i, j; 
var arr1Length = arr1.length; 
var arr2Length = arr2.length; 

for (i = 0; i < arr1Length; i++) { 
    for (j = 0; j < arr2Length; j++) { 
     if (arr1[i] === arr2[j]) { 
      commonValues.push(arr1[i]); 
     } 
    } 
} 

jsFiddle.

+0

Czytanie tego sprawiło, że zacząłem myśleć ... jaki powinien być oczekiwany rezultat przecięcia, jeśli "pozwiesz" pojawiające się "wiele razy" w jednej/obu tablicach? –

+0

@PaulS. Interesujące myśli. Sądzę, że dodawałoby to wiele razy, gdyby znajdowało się w tablicy źródłowej wiele razy. Jeśli był to problem, możesz użyć metody * upuszczania duplikatów * na wynik (lub współczynnika, jak w powyższym kodzie). – alex

21

Można użyć Array.filter:

var result = arr1.filter(function(n) { 
    return arr2.indexOf(n) > -1; 
}); 
+0

Dlaczego nie po prostu 'return arr2.indexOf (n)! == -1'? Tworzysz nową tablicę w obie strony. – Blender

+1

Filtr @alex() zwraca tablicę dopasowanych wartości, podczas gdy forEach nie zwraca niczego. –

7

Iterate nad jednym z tablicami i porównać obiekty z drugiej:

var results = []; 

for (var i = 0; i < arr1.length; i++) { 
    if (arr2.indexOf(arr1[i]) !== -1) { 
     results.push(arr1[i]); 
    } 
} 
35

Oto funkcja skrzyżowanie na podstawie Array.prototype.filter

function intersect(a, b) { 
    var t; 
    if (b.length > a.length) t = b, b = a, a = t; // indexOf to loop over shorter 
    return a.filter(function (e) { 
     return b.indexOf(e) > -1; 
    }); 
} 

var arr1 = ["mike", "sue", "tom", "kathy", "henry"]; 
    arr2 = ["howey", "jim", "sue", "jennifer", "kathy", "hank", "alex"]; 

intersect(arr1, arr2); // ["sue", "kathy"] 

Można też rozważyć następujące

var arr1 = ['sue', 'sue', 'kathy'], 
    arr2 = ['kathy', 'kathy', 'sue']; 

Powyższy będzie teraz dać ["sue", "sue", "kathy"]. Jeśli nie chcesz duplikatów, możesz zrobić dodatkowy filtr. To również ustandaryzuje wyniki. tj

return a 
    .filter(/* .. */) // same as before 
    .filter(function (e, i, c) { // extra step to remove duplicates 
     return c.indexOf(e) === i; 
    }); 

Dodawanie to spowoduje powrót ten sam wynik, jak w poprzednich układach (["sue", "kathy"]), nawet chociaż nie są duplikatami.

+1

Dzięki Paul za rozdawanie duplikatów i regularne opcje, Nice bit kodu. – JimTheDev

+0

Nie wierzę, że to zadziała, jeśli jedna z dwóch tablic jest pusta, zwróci fałszywe pozytywne ... Po prostu sprawdziłem, czy dodano. Długość – afreeland

+6

Arghh .. Nienawidzę 'if (warunek) return true; 'budowa .. Dlaczego nie' warunek zwrotu; '? –

Powiązane problemy