web-dev-qa-db-fra.com

Code le plus simple pour l'intersection de tableaux en javascript

Quel est le code le plus simple, sans bibliothèque, pour implémenter des intersections de tableaux en javascript? Je veux ecrire

intersection([1,2,3], [2,3,4,5])

et obtenir

[2, 3]
440
Peter

Utilisez une combinaison de Array.prototype.filter et Array.prototype.indexOf :

array1.filter(value => -1 !== array2.indexOf(value));
821
Anon.

La destruction semble plus simple, surtout si nous pouvons supposer que l’entrée est triée:

/* destructively finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *  State of input arrays is undefined when
 *  the function returns.  They should be 
 *  (prolly) be dumped.
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length, b.length)
 */
function intersection_destructive(a, b)
{
  var result = [];
  while( a.length > 0 && b.length > 0 )
  {  
     if      (a[0] < b[0] ){ a.shift(); }
     else if (a[0] > b[0] ){ b.shift(); }
     else /* they're equal */
     {
       result.Push(a.shift());
       b.shift();
     }
  }

  return result;
}

Non destructif doit être un poil plus compliqué, car nous devons suivre les indices:

/* finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length(), b.length())
 */
function intersect_safe(a, b)
{
  var ai=0, bi=0;
  var result = [];

  while( ai < a.length && bi < b.length )
  {
     if      (a[ai] < b[bi] ){ ai++; }
     else if (a[ai] > b[bi] ){ bi++; }
     else /* they're equal */
     {
       result.Push(a[ai]);
       ai++;
       bi++;
     }
  }

  return result;
}
153
atk

Si votre environnement prend en charge ECMAScript 6 Set , une méthode simple et supposément efficace (voir lien de spécification):

function intersect(a, b) {
  var setA = new Set(a);
  var setB = new Set(b);
  var intersection = new Set([...setA].filter(x => setB.has(x)));
  return Array.from(intersection);
}

Plus court, mais moins lisible (également sans créer l'intersection supplémentaire Set):

function intersect(a, b) {
      return [...new Set(a)].filter(x => new Set(b).has(x));
}

Éviter une nouvelle Set parmi b à chaque fois:

function intersect(a, b) {
      var setB = new Set(b);
      return [...new Set(a)].filter(x => setB.has(x));
}

Notez que lorsque vous utilisez des ensembles, vous n'obtiendrez que des valeurs distinctes. Ainsi, new Set[1,2,3,3].size est évalué à 3.

45
nbarbosa

Utiliser Underscore.js ou lodash.js

_.intersection( [0,345,324] , [1,0,324] )  // gives [0,324]
25
Sai Ram

Ma contribution en termes d'ES6. En général, il trouve l'intersection d'un tableau avec un nombre indéfini de tableaux fournis en tant qu'arguments.

Array.prototype.intersect = function(...a) {
  return [this,...a].reduce((p,c) => p.filter(e => c.includes(e)));
}
var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]],
     arr = [0,1,2,3,4,5,6,7,8,9];

document.write("<pre>" + JSON.stringify(arr.intersect(...arrs)) + "</pre>");

12
Redu

Pourquoi ne pas utiliser des tableaux associatifs?

function intersect(a, b) {
    var d1 = {};
    var d2 = {};
    var results = [];
    for (var i = 0; i < a.length; i++) {
        d1[a[i]] = true;
    }
    for (var j = 0; j < b.length; j++) {
        d2[b[j]] = true;
    }
    for (var k in d1) {
        if (d2[k]) 
            results.Push(k);
    }
    return results;
}

modifier:

// new version
function intersect(a, b) {
    var d = {};
    var results = [];
    for (var i = 0; i < b.length; i++) {
        d[b[i]] = true;
    }
    for (var j = 0; j < a.length; j++) {
        if (d[a[j]]) 
            results.Push(a[j]);
    }
    return results;
}
11
Steven Huwig

Utiliser jQuery :

var a = [1,2,3];
var b = [2,3,4,5];
var c = $(b).not($(b).not(a));
alert(c);
8
Gowsikan

Les performances de l'implémentation de @ atk pour les tableaux de primitives triés peuvent être améliorées en utilisant .pop plutôt que .shift.

function intersect(array1, array2) {
   var result = [];
   // Don't destroy the original arrays
   var a = array1.slice(0);
   var b = array2.slice(0);
   var aLast = a.length - 1;
   var bLast = b.length - 1;
   while (aLast >= 0 && bLast >= 0) {
      if (a[aLast] > b[bLast] ) {
         a.pop();
         aLast--;
      } else if (a[aLast] < b[bLast] ){
         b.pop();
         bLast--;
      } else /* they're equal */ {
         result.Push(a.pop());
         b.pop();
         aLast--;
         bLast--;
      }
   }
   return result;
}

J'ai créé un test de performance à l'aide de jsPerf: http://bit.ly/P9FrZK . Il est environ trois fois plus rapide à utiliser .pop.

8
xn.

// Return elements of array a that are also in b in linear time:
function intersect(a, b) {
  return a.filter(Set.prototype.has, new Set(b));
}

// Example:
console.log(intersect([1,2,3], [2,3,4,5]));

Je recommande ci-dessus une solution succincte qui surpasse d'autres implémentations sur de grandes entrées. Si la performance sur de petits intrants est importante, vérifiez les alternatives ci-dessous.

Alternatives et comparaison des performances:

Voir l'extrait de code suivant pour des implémentations alternatives et consultez https://jsperf.com/array-intersection-comparison pour des comparaisons de performances.

function intersect_for(a, b) {
  const result = [];
  const alen = a.length;
  const blen = b.length;
  for (let i = 0; i < alen; ++i) {
    const ai = a[i];
    for (let j = 0; j < blen; ++j) {
      if (ai === b[j]) {
        result.Push(ai);
        break;
      }
    }
  } 
  return result;
}

function intersect_filter_indexOf(a, b) {
  return a.filter(el => b.indexOf(el) !== -1);
}

function intersect_filter_in(a, b) {
  const map = b.reduce((map, el) => {map[el] = true; return map}, {});
  return a.filter(el => el in map);
}

function intersect_for_in(a, b) {
  const result = [];
  const map = {};
  for (let i = 0, length = b.length; i < length; ++i) {
    map[b[i]] = true;
  }
  for (let i = 0, length = a.length; i < length; ++i) {
    if (a[i] in map) result.Push(a[i]);
  }
  return result;
}

function intersect_filter_includes(a, b) {
  return a.filter(el => b.includes(el));
}

function intersect_filter_has_this(a, b) {
  return a.filter(Set.prototype.has, new Set(b));
}

function intersect_filter_has_arrow(a, b) {
  const set = new Set(b);
  return a.filter(el => set.has(el));
}

function intersect_for_has(a, b) {
  const result = [];
  const set = new Set(b);
  for (let i = 0, length = a.length; i < length; ++i) {
    if (set.has(a[i])) result.Push(a[i]);
  }
  return result;
}

Résultats dans Firefox 53:

  • Op/s sur de grands tableaux (10 000 éléments):

    filter + has (this)               523 (this answer)
    for + has                         482
    for-loop + in                     279
    filter + in                       242
    for-loops                          24
    filter + includes                  14
    filter + indexOf                   10
    
  • Ops/sec sur de petits tableaux (100 éléments):

    for-loop + in                 384,426
    filter + in                   192,066
    for-loops                     159,137
    filter + includes             104,068
    filter + indexOf               71,598
    filter + has (this)            43,531 (this answer)
    filter + has (arrow function)  35,588
    
8
le_m

Pour les tableaux contenant uniquement des chaînes ou des nombres, vous pouvez effectuer un tri avec les autres réponses. Pour le cas général des tableaux d'objets arbitraires, je ne pense pas que vous puissiez éviter de le faire à long terme. Ce qui suit vous donnera l'intersection d'un nombre quelconque de tableaux fournis en tant que paramètres de arrayIntersection:

var arrayContains = Array.prototype.indexOf ?
    function(arr, val) {
        return arr.indexOf(val) > -1;
    } :
    function(arr, val) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === val) {
                return true;
            }
        }
        return false;
    };

function arrayIntersection() {
    var val, arrayCount, firstArray, i, j, intersection = [], missing;
    var arrays = Array.prototype.slice.call(arguments); // Convert arguments into a real array

    // Search for common values
    firstArray = arrays.pop();
    if (firstArray) {
        j = firstArray.length;
        arrayCount = arrays.length;
        while (j--) {
            val = firstArray[j];
            missing = false;

            // Check val is present in each remaining array 
            i = arrayCount;
            while (!missing && i--) {
                if ( !arrayContains(arrays[i], val) ) {
                    missing = true;
                }
            }
            if (!missing) {
                intersection.Push(val);
            }
        }
    }
    return intersection;
}

arrayIntersection( [1, 2, 3, "a"], [1, "a", 2], ["a", 1] ); // Gives [1, "a"]; 
7
Tim Down

C'est assez court avec ES2015 et Sets. Accepte les valeurs de type tableau comme une chaîne et supprime les doublons.

let intersection = function(a, b) {
  a = new Set(a), b = new Set(b);
  return [...a].filter(v => b.has(v));
};

console.log(intersection([1,2,1,2,3], [2,3,5,4,5,3]));

console.log(intersection('ccaabbab', 'addb').join(''));

7
SeregPie
  1. Trier
  2. cochez un à l’index 0, créez un nouveau tableau à partir de celui-ci.

Quelque chose comme ça, pas bien testé cependant.

function intersection(x,y){
 x.sort();y.sort();
 var i=j=0;ret=[];
 while(i<x.length && j<y.length){
  if(x[i]<y[j])i++;
  else if(y[j]<x[i])j++;
  else {
   ret.Push(x[i]);
   i++,j++;
  }
 }
 return ret;
}

alert(intersection([1,2,3], [2,3,4,5]));

PS: l'algorithme destiné uniquement aux nombres et aux chaînes normales, l'intersection de tableaux d'objets arbitraires peut ne pas fonctionner. 

7
YOU

Un petit Tweak au plus petit ici (le filter/indexOf solution ), à savoir créer un index des valeurs dans un des tableaux en utilisant un objet JavaScript, le réduira de O (N * M) à "probablement "temps linéaire. source1source2

function intersect(a, b) {
  var aa = {};
  a.forEach(function(v) { aa[v]=1; });
  return b.filter(function(v) { return v in aa; });
}

Ce n'est pas la solution la plus simple (c'est plus de code que filter + indexOf ), ni la plus rapide (probablement plus lente d'un facteur constant que intersect_safe () ), mais cela semble être une jolie bon équilibre. Il est du côté simple {très}, tout en offrant de bonnes performances, et ne nécessite pas d'entrées triées au préalable.

5
David

Une autre approche indexée capable de traiter n’importe quel nombre de tableaux à la fois:

// Calculate intersection of multiple array or object values.
function intersect (arrList) {
    var arrLength = Object.keys(arrList).length;
        // (Also accepts regular objects as input)
    var index = {};
    for (var i in arrList) {
        for (var j in arrList[i]) {
            var v = arrList[i][j];
            if (index[v] === undefined) index[v] = 0;
            index[v]++;
        };
    };
    var retv = [];
    for (var i in index) {
        if (index[i] == arrLength) retv.Push(i);
    };
    return retv;
};

Cela ne fonctionne que pour les valeurs qui peuvent être évaluées comme des chaînes et vous devriez les passer comme un tableau comme:

intersect ([arr1, arr2, arr3...]);

... mais il accepte de manière transparente les objets en tant que paramètre ou en tant qu’un des éléments à intersecter (retourne toujours un tableau de valeurs communes). Exemples:

intersect ({foo: [1, 2, 3, 4], bar: {a: 2, j:4}}); // [2, 4]
intersect ([{x: "hello", y: "world"}, ["hello", "user"]]); // ["hello"]

EDIT: Je viens de remarquer que c'est, d'une certaine manière, légèrement buggy.

C'est-à-dire que je l'ai codé en pensant que les tableaux d'entrées ne peuvent pas contenir eux-mêmes des répétitions (comme le montre l'exemple fourni).

Mais si les tableaux d'entrées contenaient des répétitions, cela produirait des résultats erronés. Exemple (en utilisant la mise en œuvre ci-dessous):

intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]

Heureusement, il est facile de résoudre ce problème en ajoutant simplement une indexation de second niveau. C'est:

Changement:

        if (index[v] === undefined) index[v] = 0;
        index[v]++;

par:

        if (index[v] === undefined) index[v] = {};
        index[v][i] = true; // Mark as present in i input.

...et:

         if (index[i] == arrLength) retv.Push(i);

par:

         if (Object.keys(index[i]).length == arrLength) retv.Push(i);

Exemple complet:

// Calculate intersection of multiple array or object values.
function intersect (arrList) {
    var arrLength = Object.keys(arrList).length;
        // (Also accepts regular objects as input)
    var index = {};
    for (var i in arrList) {
        for (var j in arrList[i]) {
            var v = arrList[i][j];
            if (index[v] === undefined) index[v] = {};
            index[v][i] = true; // Mark as present in i input.
        };
    };
    var retv = [];
    for (var i in index) {
        if (Object.keys(index[i]).length == arrLength) retv.Push(i);
    };
    return retv;
};

intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]); // [ '1' ]
5
bitifet

Avec certaines restrictions sur vos données, vous pouvez le faire en linéaire time!

Pour entiers positifs : utilisez un tableau mappant les valeurs sur un booléen "vu/pas vu".

function intersectIntegers(array1,array2) { 
   var seen=[],
       result=[];
   for (var i = 0; i < array1.length; i++) {
     seen[array1[i]] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if ( seen[array2[i]])
        result.Push(array2[i]);
   }
   return result;
}

Il existe une technique similaire pour objects : prendre une clé factice, la définir sur "true" pour chaque élément de array1, puis rechercher cette clé dans les éléments de array2. Nettoyez quand vous avez fini.

function intersectObjects(array1,array2) { 
   var result=[];
   var key="tmpKey_intersect"
   for (var i = 0; i < array1.length; i++) {
     array1[i][key] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if (array2[i][key])
        result.Push(array2[i]);
   }
   for (var i = 0; i < array1.length; i++) {
     delete array1[i][key];
   }
   return result;
}

Bien sûr, vous devez vous assurer que la clé n'apparaît pas avant, sinon vous allez détruire vos données ... 

4
tarulen
function intersection(A,B){
var result = new Array();
for (i=0; i<A.length; i++) {
    for (j=0; j<B.length; j++) {
        if (A[i] == B[j] && $.inArray(A[i],result) == -1) {
            result.Push(A[i]);
        }
    }
}
return result;
}
4
Gabe

"indexOf" pour IE 9.0, chrome, firefox, opera, 

    function intersection(a,b){
     var rs = [], x = a.length;
     while (x--) b.indexOf(a[x])!=-1 && rs.Push(a[x]);
     return rs.sort();
    }

intersection([1,2,3], [2,3,4,5]);
//Result:  [2,3]

C'est probablement le plus simple, En plus de list1.filter (n => list2.includes (n))

var list1 = ['bread', 'ice cream', 'cereals', 'strawberry', 'chocolate']
var list2 = ['bread', 'cherry', 'ice cream', 'oats']

function check_common(list1, list2){
	
	list3 = []
	for (let i=0; i<list1.length; i++){
		
		for (let j=0; j<list2.length; j++){	
			if (list1[i] === list2[j]){
				list3.Push(list1[i]);				
			}		
		}
		
	}
	return list3
	
}

check_common(list1, list2) // ["bread", "ice cream"]

3
Chris Lwin

Je vais contribuer avec ce qui fonctionne le mieux pour moi:

if (!Array.prototype.intersect){
Array.prototype.intersect = function (arr1) {

    var r = [], o = {}, l = this.length, i, v;
    for (i = 0; i < l; i++) {
        o[this[i]] = true;
    }
    l = arr1.length;
    for (i = 0; i < l; i++) {
        v = arr1[i];
        if (v in o) {
            r.Push(v);
        }
    }
    return r;
};
}
3
Johan

.reduce pour construire une carte, et .filter pour trouver l'intersection. delete dans le .filter nous permet de traiter le second tableau comme s'il s'agissait d'un ensemble unique.

function intersection (a, b) {
  var seen = a.reduce(function (h, k) {
    h[k] = true;
    return h;
  }, {});

  return b.filter(function (k) {
    var exists = seen[k];
    delete seen[k];
    return exists;
  });
}

Je trouve cette approche assez facile à raisonner. Il effectue à temps constant.

2
Belden

'use strict'

// Example 1
function intersection(a1, a2) {
    return a1.filter(x => a2.indexOf(x) > -1)
}

// Example 2 (prototype function)
Array.prototype.intersection = function(arr) {
    return this.filter(x => arr.indexOf(x) > -1)
} 

const a1 = [1, 2, 3]
const a2 = [2, 3, 4, 5]

console.log(intersection(a1, a2))
console.log(a1.intersection(a2))

2
Vlad Bezden

Une approche fonctionnelle avec ES2015

Une approche fonctionnelle doit envisager d’utiliser uniquement des fonctions pures sans effets secondaires, chacune ne s’occupant que d’un seul travail.

Ces restrictions améliorent la composabilité et la réutilisabilité des fonctions impliquées.

// small, reusable auxiliary functions

const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const apply = f => x => f(x);


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run it

console.log( intersect(xs) (ys) );

Veuillez noter que le type Set natif est utilisé, ce qui offre une performance de recherche Avantageuse.

Éviter les doublons

Il est évident que les éléments récurrents de la première Array sont préservés, alors que la seconde Array est dédupliquée. Cela peut être ou ne pas être le comportement souhaité. Si vous avez besoin d'un résultat unique, appliquez simplement dedupe au premier argument:

// auxiliary functions

const apply = f => x => f(x);
const comp = f => g => x => f(g(x));
const afrom = apply(Array.from);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// de-duplication

const dedupe = comp(afrom) (createSet);


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// unique result

console.log( intersect(dedupe(xs)) (ys) );

Calculer l'intersection d'un nombre quelconque de Arrays

Si vous voulez calculer l'intersection d'un nombre arbitraire de Arrays, composez simplement intersect avec foldl. Voici une fonction de commodité:

// auxiliary functions

const apply = f => x => f(x);
const uncurry = f => (x, y) => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// intersection of an arbitrarily number of Arrays

const intersectn = (head, ...tail) => foldl(intersect) (head) (tail);


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
const zs = [0,1,2,3,4,5,6];


// run

console.log( intersectn(xs, ys, zs) );

2
user6445533

Pour la simplicité:

// Usage
const intersection = allLists
  .reduce(intersect, allValues)
  .reduce(removeDuplicates, []);


// Implementation
const intersect = (intersection, list) =>
  intersection.filter(item =>
    list.some(x => x === item));

const removeDuplicates = (uniques, item) =>
  uniques.includes(item) ? uniques : uniques.concat(item);


// Example Data
const somePeople = [bob, doug, jill];
const otherPeople = [sarah, bob, jill];
const morePeople = [jack, jill];

const allPeople = [...somePeople, ...otherPeople, ...morePeople];
const allGroups = [somePeople, otherPeople, morePeople];

// Example Usage
const intersection = allGroups
  .reduce(intersect, allPeople)
  .reduce(removeDuplicates, []);

intersection; // [jill]

Avantages:

  • terre simple
  • centré sur les données
  • fonctionne pour un nombre arbitraire de listes
  • fonctionne pour des longueurs arbitraires de listes
  • fonctionne pour des types de valeurs arbitraires
  • fonctionne pour un ordre de tri arbitraire
  • conserve la forme (ordre de première apparition dans un tableau)
  • quitte tôt si possible
  • mémoire en sécurité, à l'abri de toute altération des prototypes Function/Array

Désavantages:

  • utilisation accrue de la mémoire
  • utilisation accrue du processeur
  • nécessite une compréhension de réduire
  • nécessite une compréhension du flux de données

Vous ne voudriez pas utiliser ceci pour le travail du moteur 3D ou du noyau, mais si vous rencontrez des problèmes pour l'exécuter dans une application basée sur des événements, votre conception connaît de plus gros problèmes.

2
Norguard
var listA = [1,2,3,4,5,6,7];
var listB = [2,4,6,8];

var result = listA.filter(itemA=> {
    return listB.some(itemB => itemB === itemA);
});
1
jcmordan

Plutôt que d'utiliser indexOf, vous pouvez également utiliser Array.prototype.includes .

function intersection(arr1, arr2) {
  return arr1.filter((ele => {
    return arr2.includes(ele);
  }));
}

console.log(intersection([1,2,3], [2,3,4,5]));

1
AZ_

Voici underscore.js implementation:

_.intersection = function(array) {
  if (array == null) return [];
  var result = [];
  var argsLength = arguments.length;
  for (var i = 0, length = array.length; i < length; i++) {
    var item = array[i];
    if (_.contains(result, item)) continue;
    for (var j = 1; j < argsLength; j++) {
      if (!_.contains(arguments[j], item)) break;
    }
    if (j === argsLength) result.Push(item);
  }
  return result;
};

Source: http://underscorejs.org/docs/underscore.html#section-62

1
Dorian
function getIntersection(arr1, arr2){
    var result = [];
    arr1.forEach(function(elem){
        arr2.forEach(function(elem2){
            if(elem === elem2){
                result.Push(elem);
            }
        });
    });
    return result;
}

getIntersection([1,2,3], [2,3,4,5]); // [ 2, 3 ]
1
bekzat

Si vous devez le faire gérer plusieurs tableaux en intersection:

const intersect = (a, b, ...rest) => {
  if (rest.length === 0) return [...new Set(a)].filter(x => new Set(b).has(x));
  return intersect(a, intersect(b, ...rest));
};

console.log(intersect([1,2,3,4,5], [1,2], [1, 2, 3,4,5], [2, 10, 1])) // [1,2]

1
Belfordz

J'ai écrit une fonction d'intesection qui peut même détecter l'intersection d'un tableau d'objets en fonction de la propriété particulière de ces objets.

Par exemple,

if arr1 = [{id: 10}, {id: 20}]
and arr2 =  [{id: 20}, {id: 25}]

et nous voulons une intersection basée sur la propriété id, alors le résultat devrait être:

[{id: 20}]

En tant que tel, la fonction pour la même chose (remarque: code ES6) est:

const intersect = (arr1, arr2, accessors = [v => v, v => v]) => {
    const [fn1, fn2] = accessors;
    const set = new Set(arr2.map(v => fn2(v)));
    return arr1.filter(value => set.has(fn1(value)));
};

et vous pouvez appeler la fonction en tant que:

intersect(arr1, arr2, [elem => elem.id, elem => elem.id])

Remarque: cette fonction trouve une intersection en considérant que le premier tableau est le tableau principal et que le résultat de l'intersection sera donc celui du tableau principal.

1
Mridul Meharia

var arrays = [
    [1, 2, 3],
    [2, 3, 4, 5]
]
function commonValue (...arr) {
    let res = arr[0].filter(function (x) {
        return arr.every((y) => y.includes(x))
    })
    return res;
}
commonValue(...arrays);

1
user1046987

Vous n'avez pas besoin de déclarer une variable intermédiaire à l'intérieur de la fonction pour le deuxième tableau si le deuxième tableau sera toujours traité comme un set .

La solution suivante renvoie un tableau de valeurs uniques se produisant dans les deux tableaux:

const intersection = (a, b) => {
  b = new Set(b); // recycling variable
  return [...new Set(a)].filter(e => b.has(e));
};

console.log(intersection([1, 2, 3, 1, 1], [1, 2, 4])); // Array [ 1, 2 ]
0
Grant Miller

Vous pouvez utiliser un Set comme thisArg de Array#filter et prendre Set#has comme rappel.

function intersection(a, b) {
    return a.filter(Set.prototype.has, new Set(b));
}

console.log(intersection([1, 2, 3], [2, 3, 4, 5]));
0
Nina Scholz

J'espère que cela aide pour toutes les versions.

function diffArray(arr1, arr2) {
  var newArr = [];

  var large = arr1.length>=arr2.length?arr1:arr2;
  var small = JSON.stringify(large) == JSON.stringify(arr1)?arr2:arr1;
  for(var i=0;i<large.length;i++){
    var copyExists = false; 
    for(var j =0;j<small.length;j++){
      if(large[i]==small[j]){
        copyExists= true;
        break;
      }
    }
    if(!copyExists)
      {
        newArr.Push(large[i]);
      }
  }

  for(var i=0;i<small.length;i++){
    var copyExists = false; 
    for(var j =0;j<large.length;j++){
      if(large[j]==small[i]){
        copyExists= true;
        break;
      }
    }
    if(!copyExists)
      {
        newArr.Push(small[i]);
      }
  }


  return newArr;
}
0
Shubham Pandey

ES6 style simple façon.

const intersection = (a, b) => {
  const s = new Set(b);
  return a.filter(x => s.has(x));
};

Exemple:

intersection([1, 2, 3], [4, 3, 2]); // [2, 3]
0
Alex Petre

Créez un objet en utilisant un tableau et parcourez le second tableau pour vérifier si la valeur existe en tant que clé.

function intersection(arr1, arr2) {
  var myObj = {};
  var myArr = [];
  for (var i = 0, len = arr1.length; i < len; i += 1) {
    if(myObj[arr1[i]]) {
      myObj[arr1[i]] += 1; 
    } else {
      myObj[arr1[i]] = 1;
    }
  }
  for (var j = 0, len = arr2.length; j < len; j += 1) {
    if(myObj[arr2[j]] && myArr.indexOf(arr2[j]) === -1) {
      myArr.Push(arr2[j]);
    }
  }
  return myArr;
}
0
sridhar reddy

Si vos tableaux sont triés, cela devrait fonctionner en O (n), où n est min (a.length, b.length)

function intersect_1d( a, b ){
    var out=[], ai=0, bi=0, acurr, bcurr, last=Number.MIN_SAFE_INTEGER;
    while( ( acurr=a[ai] )!==undefined && ( bcurr=b[bi] )!==undefined ){
        if( acurr < bcurr){
            if( last===acurr ){
                out.Push( acurr );
            }
            last=acurr;
            ai++;
        }
        else if( acurr > bcurr){
            if( last===bcurr ){
                out.Push( bcurr );
            }
            last=bcurr;
            bi++;
        }
        else {
            out.Push( acurr );
            last=acurr;
            ai++;
            bi++;
        }
    }
    return out;
}
0
Dave Swanson

Voici une implémentation très naïve que j'utilise. Il est non destructif et évite également les doublons.

Array.prototype.contains = function(elem) {
    return(this.indexOf(elem) > -1);
};

Array.prototype.intersect = function( array ) {
    // this is naive--could use some optimization
    var result = [];
    for ( var i = 0; i < this.length; i++ ) {
        if ( array.contains(this[i]) && !result.contains(this[i]) )
            result.Push( this[i] );
    }
    return result;
}
0
devios1

Si vous souhaitez utiliser la réponse acceptée, mais que vous avez besoin d'une prise en charge d'Internet Explorer, vous devrez éviter l'annotation abrégée de la fonction de flèche. Voici le one-liner édité qui fonctionnera également dans IE:

// accepted aswer: array1.filter(value => -1 !== array2.indexOf(value));
// IE-supported syntax:
array1.filter(function(value) { return -1 !== array2.indexOf(value) });
0
KjetilNordin

Le code suivant supprime également les doublons:

       function intersect(x, y) {
            if (y.length > x.length) temp = y, y = x, x= temp;  
            return x.filter(function (e, i, c) {  
                  return c.indexOf(e) === i;
                 });
       }
0
Enayat Rajabi

intersection de N tableaux dans coffeescript

getIntersection: (arrays) ->
    if not arrays.length
        return []
    a1 = arrays[0]
    for a2 in arrays.slice(1)
        a = (val for val in a1 when val in a2)
        a1 = a
    return a1.unique()
0
user1205224

S'appuyant sur l'excellente réponse d'Anon, celle-ci renvoie l'intersection de deux ou plusieurs tableaux.

function arrayIntersect(arrayOfArrays)
{        
    var arrayCopy = arrayOfArrays.slice(),
        baseArray = arrayCopy.pop();

    return baseArray.filter(function(item) {
        return arrayCopy.every(function(itemList) {
            return itemList.indexOf(item) !== -1;
        });
    });
}
0
Dag Sondre Hansen

J'ai étendu la réponse de Tarulen pour travailler avec un nombre quelconque de tableaux. Cela devrait également fonctionner avec des valeurs non entières.

function intersect() { 
    const last = arguments.length - 1;
    var seen={};
    var result=[];
    for (var i = 0; i < last; i++)   {
        for (var j = 0; j < arguments[i].length; j++)  {
            if (seen[arguments[i][j]])  {
                seen[arguments[i][j]] += 1;
            }
            else if (!i)    {
                seen[arguments[i][j]] = 1;
            }
        }
    }
    for (var i = 0; i < arguments[last].length; i++) {
        if ( seen[arguments[last][i]] === last)
            result.Push(arguments[last][i]);
        }
    return result;
}
0
gabe appleton

fonction intersectionOfArrays (arr1, arr2) {return arr1.filter ((element) => arr2.indexOf (element)! == -1) .filter ((element, pos, self) => self.indexOf (element) == pos);}

0
Prakash Mandal