Quel est le code le plus simple et sans bibliothèque pour implémenter les intersections de tableaux en javascript? Je veux ecrire
intersection([1,2,3], [2,3,4,5])
et obtenir
[2, 3]
Quel est le code le plus simple et sans bibliothèque pour implémenter les intersections de tableaux en javascript? Je veux ecrire
intersection([1,2,3], [2,3,4,5])
et obtenir
[2, 3]
break
àSimple js loops
augmente les ops / sec à ~ 10MRéponses:
Utilisez une combinaison de
Array.prototype.filter
etArray.prototype.indexOf
:Ou comme suggéré par vrugtehagel dans les commentaires, vous pouvez utiliser le plus récent
Array.prototype.includes
pour un code encore plus simple:Pour les navigateurs plus anciens:
la source
intersection([1,2,1,1,3], [1])
retourne[1, 1, 1]
. Cela ne devrait-il pas revenir juste[1]
?array2.indexOf(n) != -1
un, vous pouvez également écrirearray2.includes(n)
pour un code encore plus simple.Destructif semble le plus simple, surtout si l'on peut supposer que l'entrée est triée:
Non destructif doit être un cheveu plus compliqué, car nous devons suivre les indices:
la source
intersect_safe
:length
est une propriété dans les tableaux, pas une méthode. Il y a une variable non repousséei
dansresult.push(a[i]);
. Enfin, cela ne fonctionne tout simplement pas dans le cas général: deux objets où ni l'un ni l'autre n'est supérieur à l'autre selon l'>
opérateur ne sont pas nécessairement égaux.intersect_safe( [ {} ], [ {} ] )
, par exemple, donnera (une fois les erreurs mentionnées ci-dessus corrigées) un tableau avec un élément, ce qui est clairement faux..slice(0)
pour créer un clone du tableau dansintersect_safe
, plutôt que de suivre les index.Si votre environnement prend en charge ECMAScript 6 Set , une manière simple et supposée efficace (voir lien de spécification):
Plus court, mais moins lisible (également sans créer l'intersection supplémentaire
Set
):Éviter une nouvelle
Set
deb
chaque fois:Notez que lors de l' utilisation des ensembles vous obtenez seulement des valeurs distinctes, donc
new Set[1,2,3,3].size
évalue à3
.la source
[...setA]
syntaxe? Un type particulier d'opération javascript?x => new Set(b).has(x)
fonction de flèche ne se transforme- t-elle pasb
en ensemble à chaque exécution? Vous devriez probablement enregistrer cet ensemble dans une variable.Utilisation de Underscore.js ou lodash.js
la source
Ma contribution en termes ES6. En général, il trouve l'intersection d'un tableau avec un nombre indéfini de tableaux fournis comme arguments.
la source
[[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8],[4,5,6,7],[4,6]]
, puis s'applique.reduce()
. La première[0,1,2,3,4,5,6,7,8,9].filter( e => [0,2,4,6,8].includes(e)
opération est effectuée et le résultat devient le nouveaup
etc
devient[4,5,6,7]
au tour suivant et continue ainsi jusqu'à ce qu'il n'enc
reste plus .prototype
inutilement.Je recommande la solution succincte ci-dessus qui surpasse les autres implémentations sur de grandes entrées. Si les performances sur les petites entrées sont importantes, vérifiez les alternatives ci-dessous.
Alternatives et comparaison des performances:
Consultez l'extrait de code suivant pour d'autres implémentations et consultez https://jsperf.com/array-intersection-comparison pour des comparaisons de performances.
Afficher l'extrait de code
Résultats dans Firefox 53:
Ops / sec sur les grands tableaux (10 000 éléments):
Ops / sec sur de petits tableaux (100 éléments):
la source
intersect([1,2,2,3], [2,3,4,5])
retourne[2, 2, 3]
.a.filter(b.includes)
. Il devrait fonctionner beaucoup plus rapidement (comme pour la mise à niveau de votre fonction).Que diriez-vous d'utiliser simplement des tableaux associatifs?
Éditer:
la source
Object.prototype
.d[b[i]] = true;
au lieu ded[b[j]] = true;
(i
nonj
). Mais l'édition nécessite 6 caractères.Quelque chose comme ça, pas bien testé cependant.
PS: l'algorithme destiné uniquement aux nombres et aux chaînes normales, l'intersection de tableaux d'objets arbitraires peut ne pas fonctionner.
la source
Les performances de l'implémentation de @ atk pour les tableaux triés de primitives peuvent être améliorées en utilisant .pop plutôt que .shift.
J'ai créé une référence à l'aide de jsPerf: http://bit.ly/P9FrZK . Il est environ trois fois plus rapide d'utiliser .pop.
la source
a[aLast] > b[bLast]
para[aLast].localeCompare(b[bLast]) > 0
(et la même chose queelse if
ci - dessous), cela fonctionnera sur les chaînes..pop
est O (1) et.shift()
est O (n)Utilisation de jQuery :
la source
c = $(b).filter(a);
, mais je ne recommanderais pas de compter sur jQuery pour ce type de manipulation de tableau, car la documentation mentionne uniquement que cela fonctionne pour les éléments.Pour les tableaux contenant uniquement des chaînes ou des nombres, vous pouvez faire quelque chose avec le tri, selon certaines des 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 de n'importe quel nombre de tableaux fournis comme paramètres pour
arrayIntersection
:la source
firstArr
ou defirstArray
ne pas mettre à jour toutes les références. Fixé.C'est assez court en utilisant ES2015 et Sets. Accepte les valeurs de type tableau comme une chaîne et supprime les doublons.
la source
Vous pouvez utiliser un
Set
asthisArg
deArray#filter
et prendreSet#has
comme rappel.la source
Un petit ajustement au plus petit ici (la solution filter / indexOf ), à savoir la création d'un index des valeurs dans l'un des tableaux à l'aide d'un objet JavaScript, le réduira de O (N * M) à un temps linéaire "probablement". source1 source2
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 un assez bon équilibre. Il est très simple, tout en offrant de bonnes performances, et il ne nécessite pas d'entrées pré-triées.
la source
Une autre approche indexée capable de traiter n'importe quel nombre de tableaux à la fois:
Cela ne fonctionne que pour les valeurs qui peuvent être évaluées en tant que chaînes et vous devez les passer sous forme de tableau comme:
... mais il accepte de manière transparente les objets comme paramètre ou comme l'un des éléments à recouper (renvoyant toujours un tableau de valeurs communes). Exemples:
EDIT: Je viens de remarquer que c'est, en quelque sorte, légèrement buggé.
C'est-à-dire: je l'ai codé en pensant que les tableaux d'entrée ne peuvent pas contenir de répétitions (comme l'exemple fourni ne le fait pas).
Mais si les tableaux d'entrée contiennent des répétitions, cela produira des résultats erronés. Exemple (en utilisant l'implémentation ci-dessous):
Heureusement, cela est facile à résoudre en ajoutant simplement une indexation de second niveau. C'est:
Changement:
par:
...et:
par:
Exemple complet:
la source
var v =
ligne, ajoutezif (typeof v == 'function') continue;
et cela sautera l'ajout de fonctions aux résultats. Merci!if (typeof v == 'function')
, alors nous pouvons utiliser sa stringification (v.toString()
) comme clé pour l'index. Mais, nous devons faire quelque chose pour le conserver intact. la manière la plus simple de le faire est simplement d'affecter la fonction d'origine en tant que valeur au lieu d'une simple valeur booléenne vraie. Mais, dans ce cas, la dernière désindexation doit également être modifiée pour détecter cette condition et restaurer la bonne valeur (la fonction).Vous pouvez utiliser (pour tous les navigateurs sauf IE):
ou pour IE:
la source
la source
Avec quelques restrictions sur vos données, vous pouvez le faire en temps linéaire !
Pour les entiers positifs : utilisez un tableau mappant les valeurs à un booléen "vu / non vu".
Il existe une technique similaire pour les objets : prenez une clé factice, définissez-la sur "true" pour chaque élément de array1, puis recherchez cette clé dans les éléments de array2. Nettoyez quand vous avez terminé.
Bien sûr, vous devez vous assurer que la clé n'apparaissait pas auparavant, sinon vous allez détruire vos données ...
la source
Je contribuerai avec ce qui a fonctionné le mieux pour moi:
la source
"indexOf" pour IE 9.0, chrome, firefox, opera,
la source
la source
Une approche fonctionnelle avec ES2015
Une approche fonctionnelle doit envisager d'utiliser uniquement des fonctions pures sans effets secondaires, dont chacune ne concerne qu'un seul travail.
Ces restrictions améliorent la composabilité et la réutilisabilité des fonctions impliquées.
Veuillez noter que le
Set
type natif est utilisé, ce qui présente des performances de recherche avantageuses.Évitez les doublons
Les éléments apparaissant de manière répétée du premier
Array
sont évidemment conservés, tandis que le secondArray
est dédoublonné. Cela peut être ou ne pas être le comportement souhaité. Si vous avez besoin d'un résultat unique, appliquez simplementdedupe
le premier argument:Calculer l'intersection de n'importe quel nombre de
Array
sSi vous voulez calculer l'intersection d'un nombre arbitraire de
Array
s composez simplementintersect
avecfoldl
. Voici une fonction pratique:la source
(expr ? true : false)
est redondant. Utilisez justeexpr
si les booléens réels ne sont pas nécessaires, juste véridiques / fausses.Pour la simplicité:
Avantages:
Désavantages:
Vous ne voudriez pas l'utiliser pour le moteur 3D ou le travail du noyau, mais si vous avez des problèmes pour que cela fonctionne dans une application basée sur des événements, votre conception a de plus gros problèmes.
la source
.reduce
pour construire une carte et.filter
trouver l'intersection.delete
dans le.filter
nous permet de traiter le deuxième tableau comme s'il s'agissait d'un ensemble unique.Je trouve cette approche assez facile à raisonner. Il fonctionne en temps constant.
la source
C'est probablement le plus simple, en plus de list1.filter (n => list2.includes (n))
la source
Si vous devez le faire gérer plusieurs tableaux entrecroisés:
la source
Manière simple de style ES6.
Exemple:
la source
J'ai écrit une fonction d'intersection 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,
et nous voulons une intersection basée sur la
id
propriété, alors la sortie devrait être:En tant que tel, la fonction pour le même (note: code ES6) est:
et vous pouvez appeler la fonction comme:
Notez également: cette fonction trouve une intersection étant donné que le premier tableau est le tableau principal et donc le résultat de l'intersection sera celui du tableau principal.
la source
Pensez que ce sera plus rapide avec le temps O (array1 + array2) en supposant que map.has () est ~ O (1). Veuillez me corriger en cas d'erreur.
la source
Voici l' implémentation underscore.js :
Source: http://underscorejs.org/docs/underscore.html#section-62
la source