Deixe A
e B
seja dois conjuntos. Estou procurando maneiras realmente rápidas ou elegantes de calcular a diferença definida ( A - B
ou A \B
, dependendo de sua preferência) entre eles. Os dois conjuntos são armazenados e manipulados como arrays Javascript, como o título diz.
Notas:
- Truques específicos do Gecko são permitidos
- Eu prefiro usar funções nativas (mas estou aberto a uma biblioteca leve se for muito mais rápida)
- Eu vi, mas não testei, JS.Set (ver ponto anterior)
Edit: Notei um comentário sobre conjuntos contendo elementos duplicados. Quando digo "conjunto", estou me referindo à definição matemática, o que significa (entre outras coisas) que eles não contêm elementos duplicados.
javascript
arrays
set-difference
Matt Ball
fonte
fonte
indexOf
implementação lenta .Respostas:
se não sei se isso é mais eficaz, mas talvez o mais curto
Atualizado para ES6:
fonte
!B.includes(x)
vez deB.indexOf(x) < 0
:)Bem, 7 anos depois, com o objeto Set do ES6 é bastante fácil (mas ainda não tão compacto quanto o do python
A - B
) e supostamente mais rápido do queindexOf
para grandes arrays:fonte
Você pode usar um objeto como um mapa para evitar a verificação linear
B
de cada elemento,A
como na resposta do usuário 187291 :O
toSource()
método não padrão é usado para obter nomes de propriedade exclusivos; se todos os elementos já tiverem representações de string exclusivas (como é o caso dos números), você pode acelerar o código eliminando astoSource()
invocações.fonte
O mais curto, usando jQuery, é:
fonte
not
não funciona mais com objetos genéricos desde 3.0.0-rc1. Consulte github.com/jquery/jquery/issues/3147Eu faria um hash da matriz B e, em seguida, manteria os valores da matriz A não presentes em B:
fonte
getDifference(a, b, hashOfB)
se não for aprovado, será calculado, caso contrário, será reutilizado como está.Incorporando a ideia de Christoph e assumindo alguns métodos de iteração não padrão em arrays e objetos / hashes (
each
e amigos), podemos obter a diferença, união e interseção no tempo linear em cerca de 20 linhas no total:Isso pressupõe que
each
efilter
são definidos para matrizes e que temos dois métodos utilitários:myUtils.keys(hash)
: retorna uma matriz com as chaves do hashmyUtils.select(hash, fnSelector, fnEvaluator)
: retorna uma matriz com os resultados da chamadafnEvaluator
dos pares chave / valor para os quaisfnSelector
retorna verdadeiro.O
select()
é vagamente inspirado no Common Lisp e é meramentefilter()
emap()
agrupado em um. (Seria melhor tê-los definidos emObject.prototype
, mas fazer isso estraga o caos com o jQuery, então me conformei com métodos utilitários estáticos.)Desempenho: Testando com
dá dois conjuntos com 50.000 e 66.666 elementos. Com esses valores, AB leva cerca de 75ms, enquanto a união e a interseção têm cerca de 150ms cada. (Mac Safari 4.0, usando data Javascript para cronometragem.)
Acho que é uma recompensa decente para 20 linhas de código.
fonte
hasOwnProperty()
mesmo se os elementos são numéricos: caso contrário, algo comoObject.prototype[42] = true;
meios42
nunca pode ocorrer no conjunto de resultadosUsando Underscore.js (biblioteca para JS funcional)
fonte
Algumas funções simples, emprestadas da resposta de @milan:
Uso:
fonte
Quanto ao modo rápido, não é muito elegante, mas fiz alguns testes para ter certeza. Carregar uma matriz como um objeto é muito mais rápido de processar em grandes quantidades:
Resultados:
No entanto, isso funciona apenas com strings . Se você planeja comparar conjuntos numerados, desejará mapear os resultados com parseFloat .
fonte
b.filter(function(v) { return !A[v]; });
na segunda função?Isso funciona, mas acho que outro é muito mais curto e elegante também
fonte