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]
Utilisez une combinaison de Array.prototype.filter
et Array.prototype.indexOf
:
array1.filter(value => -1 !== array2.indexOf(value));
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;
}
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
.
Utiliser Underscore.js ou lodash.js
_.intersection( [0,345,324] , [1,0,324] ) // gives [0,324]
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>");
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;
}
Utiliser jQuery :
var a = [1,2,3];
var b = [2,3,4,5];
var c = $(b).not($(b).not(a));
alert(c);
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.
// 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
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"];
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(''));
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.
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.
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' ]
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 ...
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;
}
"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"]
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;
};
}
.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.
'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))
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.
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) );
Array
sSi vous voulez calculer l'intersection d'un nombre arbitraire de Array
s, 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) );
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:
Désavantages:
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.
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);
});
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]));
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
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 ]
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]
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.
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);
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 ]
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]));
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;
}
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]
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;
}
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;
}
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;
}
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) });
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;
});
}
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()
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;
});
});
}
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;
}
fonction intersectionOfArrays (arr1, arr2) {return arr1.filter ((element) => arr2.indexOf (element)! == -1) .filter ((element, pos, self) => self.indexOf (element) == pos);}