68

文字列値を持つ複数の配列があり、それらを比較して、それらすべての間で同一である一致する結果のみを保持したいと思います。

このサンプルコードを考えると:

var arr1 = ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2 = ['taco', 'fish', 'apple', 'pizza'];
var arr3 = ['banana', 'pizza', 'fish', 'apple'];

指定されたすべての配列からの一致を含む次の配列を作成したいと思います。

['apple', 'fish', 'pizza']

私はすべての配列を組み合わせることができることを知っていますvar newArr = arr1.concat(arr2, arr3);が、それは私にすべてと複製を含む配列を与えるだけです。underscore.jsなどのライブラリのオーバーヘッドを必要とせずにこれを簡単に行うことができますか?

(素晴らしい、そして私もお腹が空いています!)

編集私は、配列の数が不明である可能性があることに言及する必要があると思います。私は例として3を使用していました。

4

12 に答える 12

95
var result = arrays.shift().filter(function(v) {
    return arrays.every(function(a) {
        return a.indexOf(v) !== -1;
    });
});

デモ:http: //jsfiddle.net/nWjcp/2/

最初に外側の配列を並べ替えて、最初に最短の配列を取得することができます...

arrays.sort(function(a, b) {
    return a.length - b.length;
});

完全を期すために、アレイ内の重複を処理するソリューションを次に示します。.reduce()代わりに使用し.filter()ます...

var result = arrays.shift().reduce(function(res, v) {
    if (res.indexOf(v) === -1 && arrays.every(function(a) {
        return a.indexOf(v) !== -1;
    })) res.push(v);
    return res;
}, []);

デモ:http: //jsfiddle.net/nWjcp/4/

于 2012-06-18T01:29:51.913 に答える
24

交差点を見つけたい配列の配列があると仮定すると、最も単純なシングルライナーアプローチは次のようになります。

var arr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8],[4,5,6,7]],
    int = arr.reduce((p,c) => p.filter(e => c.includes(e)));

document.write("<pre>" + JSON.stringify(int) + "</pre>");

于 2016-05-06T07:46:34.990 に答える
16

質問に不確定な数の配列を追加したので、各アイテムのカウントをオブジェクトに収集し、最大カウントを持つアイテムを照合する別のアプローチを次に示します。

このアプローチの利点:

  1. 配列が大きい場合、ブルートフォース検索オプション(他の回答で使用)よりも約15倍高速
  2. ES5またはES5シムは必要ありません(すべてのブラウザーで動作します)
  3. 完全に非破壊的(ソースデータをまったく変更しません)
  4. ソース配列内の重複アイテムを処理します
  5. 任意の数の入力配列を処理します

そしてここにコードがあります:

function containsAll(/* pass all arrays here */) {
    var output = [];
    var cntObj = {};
    var array, item, cnt;
    // for each array passed as an argument to the function
    for (var i = 0; i < arguments.length; i++) {
        array = arguments[i];
        // for each element in the array
        for (var j = 0; j < array.length; j++) {
            item = "-" + array[j];
            cnt = cntObj[item] || 0;
            // if cnt is exactly the number of previous arrays, 
            // then increment by one so we count only one per array
            if (cnt == i) {
                cntObj[item] = cnt + 1;
            }
        }
    }
    // now collect all results that are in all arrays
    for (item in cntObj) {
        if (cntObj.hasOwnProperty(item) && cntObj[item] === arguments.length) {
            output.push(item.substring(1));
        }
    }
    return(output);
}    

作業デモ: http: //jsfiddle.net/jfriend00/52mAP/

参考までに、これはES5を必要としないため、シムなしですべてのブラウザーで機能します。

1000個の長さの15個のアレイでのパフォーマンステストでは、これは、このjsperfで使用されている検索方法よりも10倍以上高速でした:http://jsperf.com/in-all-arrays


これは、ES6を使用し、重複排除してカウントを追跡するバージョンMapですSet。これには、データのタイプが保持され、何でもかまいません(自然な文字列変換を行う必要はなく、オブジェクトがまったく同じオブジェクトであるかどうかが比較されても、データはオブジェクトである可能性があるという利点があります。プロパティ/値)。

var arrays = [
    ['valueOf', 'toString','apple', 'orange', 'banana', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza', 1, 2, 999, 888],
    ['valueOf', 'toString','taco', 'fish', 'fish', 'apple', 'pizza', 1, 999, 777, 999, 1],
    ['valueOf', 'toString','banana', 'pizza', 'fish', 'apple', 'apple', 1, 2, 999, 666, 555]
    ];
    
// subclass for updating cnts    
class MapCnt extends Map {
    constructor(iterable) {
        super(iterable);
    }
    
    cnt(iterable) {
        // make sure items from the array are unique
        let set = new Set(iterable);
        // now update the cnt for each item in the set
        for (let item of set) {
            let cnt = this.get(item) || 0;
            ++cnt;
            this.set(item, cnt);
        }
    }
}


function containsAll(...allArrays) {
    let cntObj = new MapCnt();
    for (array of allArrays) {
        cntObj.cnt(array);
    }
    // now see how many items have the full cnt
    let output = [];
    for (var [item, cnt] of cntObj.entries()) {
        if (cnt === allArrays.length) {
            output.push(item);
        }
    }
    return(output);
}    

var result = containsAll.apply(this, arrays);

document.body.innerHTML = "<pre>[<br>    " + result.join(',<br>    ') + "<br>]</pre>";

于 2012-06-18T01:30:58.167 に答える
3

いくつかの考え-最短の配列の項目だけを比較し、返された配列の重複を防ぐことができます。

function arraysInCommon(arrays){
    var i, common,
    L= arrays.length, min= Infinity;
    while(L){
        if(arrays[--L].length<min){
            min= arrays[L].length;
            i= L;
        }
    }
    common= arrays.splice(i, 1)[0];
    return common.filter(function(itm, indx){
        if(common.indexOf(itm)== indx){
            return arrays.every(function(arr){
                return arr.indexOf(itm)!= -1;
            });
        }
    });
}

var arr1= ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2= ['taco', 'fish', 'apple', 'pizza', 'apple','apple'];
var arr3= ['banana', 'pizza', 'fish', 'apple','fish'];

var allArrays = [arr1,arr2,arr3];

arraysInCommon(allArrays).sort();

戻り値:apple,fish,pizza

デモ-http : //jsfiddle.net/kMcud/

于 2012-06-18T03:44:22.090 に答える
2

配列の配列を想定し、すべての配列をチェックします。

デモ:http://jsfiddle.net/qUQHW/

var tmp = {};
for (i = 0; i < data.length; i++) {
    for (j = 0; j < data[i].length; j++) {
        if (!tmp[data[i][j]]) {
            tmp[data[i][j]] = 0;
        }
        tmp[data[i][j]]++;
    }
}

var results = $.map(tmp, function(val,key) {
    return val == data.length ? key :null;
})
于 2012-06-18T02:00:38.250 に答える
2

ここに単一行のソリューションがあります。あなたはそれを2つの思考ステップに分けることができます:

  1. 2つの配列間の結合/交差を計算します

var arrA = [1,2,3,4,5];
var arrB = [4,5,10];
var innerJoin = arrA.filter(el=>arrB.includes(el));
console.log(`Intersection is: ${innerJoin}`);

  1. 内容を減らす:累積された交差と次の配列の間の交差を計算します。

var arrays = [
 ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'],
 ['taco', 'fish', 'apple', 'pizza'],
 ['banana', 'pizza', 'fish', 'apple']
];
var join = arrays.reduce((join, current) => join.filter(el => current.includes(el)));
console.log(`Intersection is: ${join}`);

于 2017-11-03T12:31:22.177 に答える
2
    // The easiest way!! 
    
    var arr1 = ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
    var arr2 = ['taco', 'fish', 'apple', 'pizza'];
    var arr3 = ['banana', 'pizza', 'fish', 'apple'];
    var arr4 = [];


    for(let i of arr1){
      if(arr2.includes(i) && arr3.includes(i)){
        arr4.push(i)
      }
    }

    console.log(arr4)


------------- OR -----------------


arr4 = arr1.filter(value => arr2.includes(value) && arr3.includes(value))
于 2019-11-08T06:15:38.410 に答える
1

これは、任意の数のアレイで機能するはずです。

function intersection(arr1, arr2) {
  var temp = [];

  for (var i in arr1) {
    var element = arr1[i];

    if (arr2.indexOf(element) > -1) {
      temp.push(element);
    }
  }

  return temp;
}

function multi_intersect() {
  var arrays = Array.prototype.slice.apply(arguments).slice(1);
  var temp = arguments[0];

  for (var i in arrays) {
    temp = intersection(arrays[i], temp);

    if (temp == []) {
      break;
    }
  }

  return temp;
}

var arr1 = ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2 = ['taco', 'fish', 'apple', 'pizza'];
var arr3 = ['banana', 'pizza', 'fish', 'apple'];

multi_intersect(arr1, arr2, arr3);
于 2012-06-18T01:41:16.370 に答える
0

それの一体のために、別の長い手によるアプローチ:

function getCommon(a) {

  // default result is copy of first array
  var result = a[0].slice();
  var mem, arr, found = false;

  // For each member of result, see if it's in all other arrays
  // Go backwards so can splice missing entries
  var i = result.length;

  while (i--) {
    mem = result[i];

    // Check in each array
    for (var j=1, jLen=a.length; j<jLen; j++) {
      arr = a[j];
      found = false;

      // For each member of arr and until found
      var k = arr.length;
      while (k-- && !found) {

        // If found in this array, set found to true
        if (mem == arr[k]) {
          found = true;
        }
      }
      // if word wasn't found in this array, remove it from result and 
      // start on next member of result, skip remaining arrays.
      if (!found) {
        result.splice(i,1);
        break;
      }
    }
  }
  return result;
}

var data = [
  ['taco', 'fish', 'apple', 'pizza', 'mango', 'pear'],
  ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'],
  ['banana', 'pizza', 'fish', 'apple'],
  ['banana', 'pizza', 'fish', 'apple', 'mango', 'pear']
];

編集

Object.prototypeのthiseに基づいて、決して列挙できないプロパティを検索する関数:

// Return an array of Object.prototype property names that are not enumerable
// even when added directly to an object.
// Can be helpful with IE as properties like toString are not enumerable even
// when added to an object.
function getNeverEnumerables() {

    // List of Object.prototype property names plus a random name for testing
    var spNames = 'constructor toString toLocaleString valueOf ' +
                  'hasOwnProperty isPrototypeOf propertyIsEnumerable foo';

    var spObj = {foo:'', 'constructor':'', 'toString':'', 'toLocaleString':'', 'valueOf':'',
                 'hasOwnProperty':'', 'isPrototypeOf':'', 'propertyIsEnumerable':''};

    var re = [];

    // BUild list of enumerable names in spObj
    for (var p in spObj) {
      re.push(p); 
    }

    // Remove enumerable names from spNames and turn into an array
    re = new RegExp('(^|\\s)' + re.join('|') + '(\\s|$)','g');
    return spNames.replace(re, ' ').replace(/(^\s+)|\s\s+|(\s+$)/g,'').split(' ');
}

document.write(getNeverEnumerables().join('<br>'));
于 2012-06-18T03:12:30.447 に答える
0

これは基本的に、要約されたすべての回答をまとめたものです。

	 // Intersect any number of arrays:

	function intersect() {

	  // - Arguments -> traditional array,
	  // - First item ( arrays[0] ) = shortest to reduce iterations
	  var arrays = Array.prototype.slice.call(arguments).sort(function(a, b) {
	    return a.length - b.length;
	  });

	  // Use first array[0] as the base.
	  var a = arrays.shift();

	  var result = [];
	  for (var i = a.length; i--;) {

	    var val = a[i];

	    // Prevent duplicates
	    if (result.indexOf(val) < 0) {

	      // Seek
	      var found = true;
	      for (var ii = arrays.length; ii--;) {
	        if (arrays[ii].indexOf(val) < 0) {
	          found = false;
	          break;
	        }
	      }

	      if (found) {
	        result.push(val);
	      }

	    }

	  }

	  return result;

	}

	/*
	// Slower, but smaller code-base:
	function intersect (){
		
		// - Arguments -> traditional array,
		// - First item ( arrays[0] ) = shortest to reduce iterations
		var arrays = Array.prototype.slice.call(arguments).sort(function(a, b) {
	        return a.length - b.length;
	    });
		
		// Use first array[0] as the base.
		var a = arrays.shift();

		return a.filter(function (val, idx, aa) {
			
						// Seek
		                for(var i=arrays.length; i--;){
		                    if (arrays[i].indexOf(val) < 0) {
							    return false;
						    }
		                }
						
						// Prevent duplicates
		                return aa.indexOf(val) === idx;
		
					});

	}
	*/

	var arr1 = ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
	var arr2 = ['taco', 'fish', 'apple', 'pizza', 'apple', 'apple'];
	var arr3 = ['banana', 'pizza', 'fish', 'apple', 'fish'];

	var arr1 = ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
	var arr2 = ['taco', 'fish', 'apple', 'pizza', 'apple', 'apple'];
	var arr3 = ['banana', 'pizza', 'fish', 'apple', 'fish'];


	var result = intersect(arr1, arr2, arr3);

	 // For fiddle output:
	var elem = document.getElementById("result");
	elem.innerHTML = JSON.stringify(result);
	console.log(result);
<div id="result">Results</div>

于 2016-05-19T08:19:40.360 に答える
0

array#reduceとを使用できますarray#filter。配列ごとに、すべての一意の値を取得し、Mapルックアップでそれらの数を保持します。完了すると、array#filterこのルックアップは配列の長さに基づいて行われます。

const commonElements = (...arr) => {
  const lookup = arr.reduce((map, a) => {
    const unique = [...new Set(a)];
    unique.forEach(v => {
      map.set(v, (map.get(v) || 0) + 1)
    });
    return map;
  },new Map());
  return [...lookup.keys()].filter(k => lookup.get(k) === arr.length);
}

const arr1 = ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'],
      arr2 = ['taco', 'fish', 'apple', 'pizza'],
      arr3 = ['banana', 'pizza', 'fish', 'apple'];
console.log(commonElements(arr1,arr2,arr3));

于 2020-06-24T05:47:25.680 に答える
0

別の1つの解決策:

const arr1 = ['apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
const arr2 = ['taco', 'fish', 'apple', 'pizza'];
const arr3 = ['banana', 'pizza', 'fish', 'apple'];
const combinedArr = [arr1, arr2, arr3];

const result  = combinedArr
    .flatMap(([...values]) => values)
    .filter((value, index, coll) => (coll.indexOf(value) === index) && combinedArr.every(
        (values) => values.includes(value)
    ));
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

于 2021-12-23T10:18:40.107 に答える