Soit A
et B
soit deux ensembles. Je recherche des moyens très rapides ou élégants de calculer la différence d'ensemble ( A - B
ou A \B
, selon vos préférences) entre eux. Les deux ensembles sont stockés et manipulés sous forme de tableaux Javascript, comme l'indique le titre.
Remarques:
- Les astuces spécifiques à Gecko sont acceptables
- Je préférerais m'en tenir aux fonctions natives (mais je suis ouvert à une bibliothèque légère si c'est beaucoup plus rapide)
- J'ai vu, mais pas testé, JS.Set (voir point précédent)
Edit: J'ai remarqué un commentaire sur les ensembles contenant des éléments en double. Quand je dis «ensemble», je fais référence à la définition mathématique, ce qui signifie (entre autres) qu'ils ne contiennent pas d'éléments en double.
javascript
arrays
set-difference
Matt Ball
la source
la source
indexOf
implémentation lente .Réponses:
si je ne sais pas si c'est le plus efficace, mais peut-être le plus court
Mis à jour vers ES6:
la source
!B.includes(x)
place deB.indexOf(x) < 0
:)Eh bien, 7 ans plus tard, avec l' objet Set d' ES6, c'est assez facile (mais toujours pas aussi compact que celui de python
A - B
), et apparemment plus rapide queindexOf
pour les grands tableaux:la source
Vous pouvez utiliser un objet comme carte pour éviter de balayer linéairement
B
chaque élémentA
comme dans la réponse de user187291 :La
toSource()
méthode non standard est utilisée pour obtenir des noms de propriétés uniques; si tous les éléments ont déjà des représentations de chaîne uniques (comme c'est le cas avec les nombres), vous pouvez accélérer le code en supprimant lestoSource()
appels.la source
Le plus court, en utilisant jQuery, est:
la source
not
ne fonctionne plus avec les objets génériques à partir de 3.0.0-rc1. Voir github.com/jquery/jquery/issues/3147Je hacherais le tableau B, puis conserverais les valeurs du tableau A non présentes dans B:
la source
getDifference(a, b, hashOfB)
s'il n'est pas passé, il sera calculé sinon il est réutilisé tel quel.En incorporant l'idée de Christoph et en supposant quelques méthodes d'itération non standard sur des tableaux et des objets / hachages (
each
et amis), nous pouvons obtenir la différence, l'union et l'intersection en temps linéaire sur environ 20 lignes au total:Cela suppose que
each
etfilter
sont définis pour les tableaux, et que nous avons deux méthodes utilitaires:myUtils.keys(hash)
: retourne un tableau avec les clés du hachagemyUtils.select(hash, fnSelector, fnEvaluator)
: renvoie un tableau avec les résultats de l'appelfnEvaluator
sur les paires clé / valeur pour lesquellesfnSelector
renvoie true.Le
select()
est vaguement inspiré par Common Lisp, et est simplementfilter()
etmap()
roulé en un seul. (Il serait préférable de les définir surObject.prototype
, mais cela fait des ravages avec jQuery, alors j'ai opté pour des méthodes utilitaires statiques.)Performance: test avec
donne deux ensembles de 50 000 et 66 666 éléments. Avec ces valeurs, AB prend environ 75 ms, tandis que l'union et l'intersection sont d'environ 150 ms chacune. (Mac Safari 4.0, utilisant la date Javascript pour le timing.)
Je pense que c'est une récompense décente pour 20 lignes de code.
la source
hasOwnProperty()
même si les éléments sont numériques: sinon, quelque chose comme desObject.prototype[42] = true;
moyens42
ne peut jamais se produire dans le jeu de résultatsUtilisation de Underscore.js (bibliothèque pour JS fonctionnel)
la source
Quelques fonctions simples, empruntées à la réponse de @ milan:
Usage:
la source
En ce qui concerne le jeûne, ce n'est pas si élégant, mais j'ai effectué des tests pour en être sûr. Le chargement d'un tableau en tant qu'objet est beaucoup plus rapide à traiter en grande quantité:
Résultats:
Cependant, cela ne fonctionne qu'avec des chaînes . Si vous envisagez de comparer des ensembles numérotés, vous voudrez mapper les résultats avec parseFloat .
la source
b.filter(function(v) { return !A[v]; });
dans la deuxième fonction?Cela fonctionne, mais je pense qu'un autre est beaucoup plus court et élégant aussi
la source