2012-09-15 46 views
20

私は2つの配列を持っており、2つの配列を比較し、一致する値だけを返すようにしたいと考えています。たとえば、両方の配列の値がcatなので、これが返されます。私はこのようなものは見つけていない。類似点を返す最良の方法は何でしょうか?私は書式設定を行うことができますので答えとして行わ2つの配列で一致する値を見つける方法はありますか?

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

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

答えて

31

は当然のことながら、私のアプローチは、一度最初の配列をループしたインデックスをチェック2番目の配列の各値のインデックスが> -1の場合は、返された配列にpushを置きます。それは少し速く実行できますので、他の人がやるように私のソリューションは、2つのループを使用していない

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

。あなたがfor..inを使用しないようにしたい場合は、すべてのそれらの値のインデックスを再作成するために最初の両方の配列をソートすることができます:あなたはアレイを拡張するとの問題/問題がある場合

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

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

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; 
}; 

使い方は次のようになります。このプロトタイプを関数に簡単に変更することができます。

var diff = function(arr, arr2) { 

そしてfuncはもともとarr2thisを言ったところ、あなたはどこにでも変更したいです。

+1

'.indexOf()'はループを移動するだけです。このメソッドはターゲット配列を内部的にループします。 (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf) –

+0

'.indexOf()'関数はおそらく、互換性のようにすべての配列をループするよりも高速です代替。 – jeremy

+0

indexOf()はソート後にバイナリ検索を使用するのに十分なスマートなのでしょうか?そうでなければ、O(N^2)です。リニアスキャンを実行するindexOf()のために本質的にネストされたループを実行しているからです。この問題がなくても、オブジェクトをハッシュテーブルとして使用して線形時間でこれを行うことができるときに、ソートの線形コストが発生するのはなぜですか? – ChaseMedallion

1

...

これは、あなたが通過する必要があるプロセスです。詳細については配列をループする。

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

これはtを使用します彼は**配列1の長さ*配列2の長さ**ループの量...この場合は24ループ.. array1の値のインデックスがarray2に存在するかどうかを確認してから1つのループのみが使用されます。私の答えを見てください。 – jeremy

+0

私はそれについて考えました。 '.indexOf()'はまだどこでもサポートされていませんが、少なくともMozillaのmonkeypatchバージョン(https://developer.mozilla.org/)では '.indexOf()'を簡単に使うことができます。 en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf)はまだループします。ループの1つを代わりに 'indexOf'関数に移動するだけです。 –

+0

これは、すべての主要なブラウザでサポートされています。互換表を見てください... – jeremy

7

最初の配列の要素を反復処理するたびに2番目の配列をループし、一致するものがあるかどうかを確認します。

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

これは、配列1の長さ**配列2の長さ**ループの量...この場合は24ループを使用します。 – jeremy

+0

それを指摘してくれてありがとう:) – 0x499602D2

+0

問題はありません。それは動作しますが、それは非常に不必要で、潜在的に実行するために永遠にかかる可能性があります。あなたはおそらくより良い1ループソリューションのために私の答えをチェックアウトすることができます – jeremy

0

あなたの値がnull以外の文字列や数値である場合、あなたは辞書としてオブジェクトを使用することができます。

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

2ループを使用します。他のソリューションより優れていますが、1にすることができます – jeremy

9

この関数は、O(n*m)(ループを持つ他の解決法で見られるように/ indexOf)と比較してO(n log(n) + m log(m))で実行されます。これは多くの値を扱う場合に便利です。

ただし、"a" > 1"a" < 1のどちらもないため、これは同じタイプの要素に対してのみ機能します。

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; 
} 

例:アンダースコアとlodashなどの

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

複雑さは実際にはO(nlogn + mlogm + n + m)です。計算中にwhileループを考慮するのを忘れてしまった。 – Partha

+0

@Partha 'n'は、より速く成長する' nlogn'によって包含され、 'm'と' mlogn'にも同じことが当てはまります。 – 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

ライブラリは、渡された配列内の一致を検索するintersectionと呼ばれるユーティリティメソッドを持っています。@hanuはあなたがlodashを使用することができます述べたようにhttp://underscorejs.org/#intersection

+0

良い点@EricLeschinski。私は自分の答えを変更しました。 – leojh

2

しかし、あなたはまたしてネイティブのJavaScriptを使用することができます:を見て、私は私のために完全に働いたことを提案するもの@ jota3に若干の変更を見つけ

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

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

いくつかのES6で

0

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

このスニペットはまたdefaultArrayの順

等に基づいてfirstArrを並べ替え:

HTTPと同様に
let firstArr = ['apple', 'kiwi', 'banana']; 
let defaultArray = ['kiwi', 'apple', 'pear']; 
... 
console.log(sortedArray); 
// ['kiwi', 'apple']; 
関連する問題