2012-09-15 14 views
20

Ho due array e voglio essere in grado di confrontare i due e restituire solo i valori corrispondenti. Ad esempio entrambi gli array hanno il valore cat, quindi è quello che verrà restituito. Non ho trovato nulla di simile. Quale sarebbe il modo migliore per restituire somiglianze?Come posso trovare valori corrispondenti in due array?

var array1 = ["cat", "sum","fun", "run"]; 
var array2 = ["bat", "cat","dog","sun", "hut", "gut"]; 

if array1 value is equal to array2 value then return match: cat 
+0

simile a http: // stackoverflow.com/questions/1885557/simplest-code-for-array-intersection-in-javascript –

risposta

31

Naturalmente, il mio approccio è stato quello di scorrere il primo array una volta e verificare l'indice di ogni valore nel secondo array. Se l'indice è > -1, quindi push sull'array restituito.

​Array.prototype.diff = function(arr2) { 
    var ret = []; 
    for(var i in this) { 
     if(arr2.indexOf(this[i]) > -1){ 
      ret.push(this[i]); 
     } 
    } 
    return ret; 
}; 

La mia soluzione non fa uso di due cicli come gli altri fanno così può funzionare un po 'più veloce. Se si vuole evitare di utilizzare for..in, è possibile ordinare entrambi gli array prima reindicizzare tutti i loro valori:

Array.prototype.diff = function(arr2) { 
    var ret = []; 
    this.sort(); 
    arr2.sort(); 
    for(var i = 0; i < this.length; i += 1) { 
     if(arr2.indexOf(this[i]) > -1){ 
      ret.push(this[i]); 
     } 
    } 
    return ret; 
}; 

Uso sarà simile:

var array1 = ["cat", "sum","fun", "run", "hut"]; 
var array2 = ["bat", "cat","dog","sun", "hut", "gut"]; 

console.log(array1.diff(array2)); 

Se si dispone di un problema/problema con l'estensione del Array prototipo, potresti facilmente cambiarlo in una funzione.

var diff = function(arr, arr2) { 

E che ci si cambia ovunque dove il func originariamente detto this a arr2.

+1

'.indexOf()' sposta semplicemente il ciclo. Il metodo scorre all'interno della matrice di destinazione internamente. (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf) –

+0

la funzione '.indexOf()' è probabilmente più veloce del looping di tutti gli array come fatto nella compatibilità alternativa. – jeremy

+0

IndexOf() è abbastanza intelligente da utilizzare una ricerca binaria dopo l'ordinamento? Altrimenti, questo è O (N^2) poiché si sta essenzialmente facendo un ciclo annidato a causa di indexOf() che esegue una scansione lineare. Anche senza questo problema, perché incorrere nel costo linearithmic di ordinamento quando puoi farlo in tempo lineare usando un oggetto come tabella hash? – ChaseMedallion

1

Fatto come una risposta così posso fare la formattazione ...

Questo è il processo è necessario passare attraverso. Looping attraverso una matrice per le specifiche.

create an empty array 
loop through array1, element by element. { 
    loop through array2, element by element { 
    if array1.element == array2.element { 
     add to your new array 
    } 
    } 
} 
+0

questo usa t he ** length of array 1 * la lunghezza dell'array 2 ** quantità di loop ... 24 loop in questo caso ... sarebbe meglio controllare se l'indice del valore in array1 è presente in array2 e quindi sarebbe stato utilizzato solo 1 ciclo. guarda la mia risposta – jeremy

+0

Ci ho pensato. '.indexOf()' still non è supportato ovunque, sebbene possa essere monkeypatched abbastanza facilmente ... e '.indexOf()', almeno nella versione di Mozkey monkeypatch (https://developer.mozilla.org/ en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf) loop ancora. Invece sposta semplicemente uno dei loop nella funzione 'indexOf'. –

+0

È supportato in tutti i principali browser, guarda la tabella di compatibilità ... – jeremy

7

Passare attraverso il secondo array ogni volta che si esegue iterazione su un elemento nel primo array, quindi verificare le corrispondenze.

var array1 = ["cat", "sum", "fun", "run"], 
    array2 = ["bat", "cat", "dog", "sun", "hut", "gut"]; 

function getMatch(a, b) { 
    var matches = []; 

    for (var i = 0; i < a.length; i++) { 
     for (var e = 0; e < b.length; e++) { 
      if (a[i] === b[e]) matches.push(a[i]); 
     } 
    } 
    return matches; 
} 

getMatch(array1, array2); // ["cat"] 
+0

utilizza la ** lunghezza dell'array 1 * la lunghezza dell'array 2 ** quantità di loop ... 24 loop in questo caso. – jeremy

+0

Oops. Grazie per avermelo fatto notare :) – 0x499602D2

+0

nessun problema. funziona, ma è semplicemente estremamente inutile e potrebbe potenzialmente richiedere l'eternità per essere eseguito. è possibile controllare la mia risposta per probabilmente una migliore soluzione a 1 ciclo – jeremy

0

Se i valori sono stringhe o numeri non nulli, è possibile utilizzare un oggetto come un dizionario:

var map = {}, result = [], i; 
for (i = 0; i < array1.length; ++i) { 
    map[array1[i]] = 1; 
} 

for (i = 0; i < array2.length; ++i) { 
    if (map[array2[i]] === 1) { 
     result.push(array2[i]); 

     // avoid returning a value twice if it appears twice in array 2 
     map[array2[i]] = 0; 
    } 
} 

return result; 
+0

utilizza 2 cicli. meglio di altre soluzioni, ma è possibile portarlo a 1 – jeremy

9

Questa funzione viene eseguita in O(n log(n) + m log(m)) rispetto a O(n*m) (come visto nelle altre soluzioni con loop/indexOf) che può essere utile se si hanno a che fare con molti valori.

Tuttavia, poiché né "a" > 1"a" < 1, questo funziona solo per elementi dello stesso tipo.

function intersect_arrays(a, b) { 
    var sorted_a = a.concat().sort(); 
    var sorted_b = b.concat().sort(); 
    var common = []; 
    var a_i = 0; 
    var b_i = 0; 

    while (a_i < a.length 
      && b_i < b.length) 
    { 
     if (sorted_a[a_i] === sorted_b[b_i]) { 
      common.push(sorted_a[a_i]); 
      a_i++; 
      b_i++; 
     } 
     else if(sorted_a[a_i] < sorted_b[b_i]) { 
      a_i++; 
     } 
     else { 
      b_i++; 
     } 
    } 
    return common; 
} 

Esempio:

var array1 = ["cat", "sum", "fun", "hut"], //modified for additional match 
    array2 = ["bat", "cat", "dog", "sun", "hut", "gut"]; 
intersect_arrays(array1, array2); 
>> ["cat", "hut"] 
+0

La complessità è in realtà O (nlogn + mlogm + n + m), tu ho dimenticato di considerare il ciclo while durante il calcolo. – Partha

+0

@Partha 'n' è il più veloce in crescita' n logn', lo stesso vale per 'm' e' m log n'. – phant0m

1
use lodash 
GLOBAL.utils = require('lodash') 
var arr1 = ['first' , 'second']; 
var arr2 = ['second ']; 

var result = utils.difference (arr1 , arr2); 
    console.log ("result :" + result); 
2

librerie come sottolineatura e lodash hanno un metodo di utilità chiamato intersection per trovare le corrispondenze in array passati in.Date un'occhiata a: http://underscorejs.org/#intersection

+0

Buon punto @EricLeschinski. Ho modificato la mia risposta. – leojh

2

Come @hanu accennato si potrebbe usare lodash, ma è anche possibile utilizzare javascript nativa con:

const intersection = array1.filter(element => array2.includes(element)); 
0

ho trovato una leggera alterazione di ciò che jota3 @ suggerito funzionato perfettamente per me .

var intersections = array1.filter(e => array2.indexOf(e) !== -1); 

Spero che questo aiuti!

0

Con un po 'ES6:

let sortedArray = []; 
firstArr.map((first) => { 
    sortedArray[defaultArray.findIndex(def => def === first)] = first; 
}); 
sortedArray = sortedArray.filter(v => v); 

Questo frammento smista anche il firstArr in base all'ordine del defaultArray

come:

let firstArr = ['apple', 'kiwi', 'banana']; 
let defaultArray = ['kiwi', 'apple', 'pear']; 
... 
console.log(sortedArray); 
// ['kiwi', 'apple']; 
Problemi correlati