Sea A
y B
sea dos conjuntos. Estoy buscando formas realmente rápidas o elegantes de calcular la diferencia establecida ( A - B
o A \B
, según su preferencia) entre ellas. Los dos conjuntos se almacenan y manipulan como matrices Javascript, como dice el título.
Notas:
- Los trucos específicos de Gecko están bien
- Preferiría ceñirme a las funciones nativas (pero estoy abierto a una biblioteca ligera si es mucho más rápida)
- He visto, pero no probado, JS.Set (ver punto anterior)
Editar: noté un comentario sobre conjuntos que contienen elementos duplicados. Cuando digo "conjunto" me refiero a la definición matemática, lo que significa (entre otras cosas) que no contienen elementos duplicados.
javascript
arrays
set-difference
Matt Ball
fuente
fuente
indexOf
implementación lenta .Respuestas:
si no sé si esto es más efectivo, pero quizás el más corto
Actualizado a ES6:
fuente
!B.includes(x)
lugar deB.indexOf(x) < 0
:)Bueno, 7 años después, con el objeto Set de ES6 es bastante fácil (pero aún no tan compacto como el de Python
A - B
) y, según se informa, más rápido queindexOf
para arreglos grandes:fuente
Puede usar un objeto como mapa para evitar la exploración lineal
B
de cada elemento deA
como en la respuesta del usuario187291 :El
toSource()
método no estándar se utiliza para obtener nombres de propiedad únicos; si todos los elementos ya tienen representaciones de cadenas únicas (como es el caso de los números), puede acelerar el código eliminando lastoSource()
invocaciones.fuente
El más corto, usando jQuery, es:
fuente
not
ya no funciona con objetos genéricos a partir de 3.0.0-rc1. Ver github.com/jquery/jquery/issues/3147Haría hash en la matriz B, luego mantendría los valores de la matriz A que no están presentes en B:
fuente
getDifference(a, b, hashOfB)
si no se pasa, se calculará, de lo contrario, se reutilizará como está.Incorporando la idea de Christoph y asumiendo un par de métodos de iteración no estándar en matrices y objetos / hashes (
each
y amigos), podemos obtener la diferencia de conjuntos, la unión y la intersección en tiempo lineal en aproximadamente 20 líneas en total:Esto supone que
each
yfilter
están definidos para matrices, y que tenemos dos métodos de utilidad:myUtils.keys(hash)
: devuelve una matriz con las claves del hashmyUtils.select(hash, fnSelector, fnEvaluator)
: devuelve una matriz con los resultados de llamarfnEvaluator
a los pares clave / valor para los quefnSelector
devuelve verdadero.El
select()
está vagamente inspirado en Common Lisp, y es simplementefilter()
ymap()
en uno. (Sería mejor tenerlos definidosObject.prototype
, pero hacerlo arruina el caos con jQuery, así que me conformé con métodos de utilidad estáticos).Rendimiento: prueba con
da dos conjuntos con 50.000 y 66.666 elementos. Con estos valores AB tarda unos 75 ms, mientras que la unión y la intersección son de unos 150 ms cada una. (Mac Safari 4.0, usando Javascript Date para la sincronización).
Creo que es una recompensa decente por 20 líneas de código.
fuente
hasOwnProperty()
incluso si los elementos son numéricos: de lo contrario, algo como losObject.prototype[42] = true;
medios42
nunca puede ocurrir en el conjunto de resultadosUsando Underscore.js (biblioteca para JS funcional)
fuente
Algunas funciones simples, tomadas de la respuesta de @ milan:
Uso:
fuente
En cuanto a la forma de ayuno, no es tan elegante, pero he realizado algunas pruebas para estar seguro. La carga de una matriz como objeto es mucho más rápida de procesar en grandes cantidades:
Resultados:
Sin embargo, esto solo funciona con cadenas . Si planea comparar conjuntos numerados, querrá mapear los resultados con parseFloat .
fuente
b.filter(function(v) { return !A[v]; });
en la segunda función?Esto funciona, pero creo que otro es mucho más corto y elegante también.
fuente