Eu tenho um objeto que contém uma matriz de objetos.
things = new Object();
things.thing = new Array();
things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});
Gostaria de saber qual é o melhor método para remover objetos duplicados de uma matriz. Então, por exemplo, as coisas. Tudo se tornaria ...
{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}
javascript
arrays
object
duplicates
Travis
fonte
fonte
aaaaa.aaaa.push(...)
:)Respostas:
Um método primitivo seria:
fonte
Que tal com um pouco de
es6
mágica?URL de referência
Uma solução mais genérica seria:
Exemplo Stackblitz
fonte
things.thing = things.thing.filter((thing, index, self) => self.findIndex(t => t.place === thing.place && t.name === thing.name) === index)
const uniqueArray = arrayOfObjects.filter((object,index) => index === arrayOfObjects.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object)));
jsfiddle.net/x9ku0p7L/28Se você pode usar bibliotecas Javascript, como sublinhado ou lodash, eu recomendo dar uma olhada na
_.uniq
função em suas bibliotecas. Delodash
:Basicamente, você transmite a matriz que aqui é um objeto literal e o atributo que deseja remover duplicatas na matriz de dados original, assim:
ATUALIZAÇÃO : Lodash agora introduziu um
.uniqBy
também.fonte
uniqBy
vez deuniq
, por exemplo_.uniqBy(data, 'name')
... documentação: lodash.com/docs#uniqByEu tinha exatamente esse mesmo requisito, para remover objetos duplicados em uma matriz, com base em duplicatas em um único campo. Encontrei o código aqui: Javascript: Remover duplicatas da matriz de objetos
Portanto, no meu exemplo, estou removendo qualquer objeto da matriz que tenha um valor duplicado da sequência licenseNum.
Os resultados:
uniqueArray é:
fonte
for(var i in array) { if(array[i][prop]){ //valid lookupObject[array[i][prop]] = array[i]; } else { console.log('falsy object'); } }
for (let i in originalArray) { if (lookupObject[originalArray[i]['id']] === undefined) { newArray.push(originalArray[i]); } lookupObject[originalArray[i]['id']] = originalArray[i]; }
Forros um mais curtos para ES6 +
Encontre os exclusivos
id
em uma matriz.Exclusivo por várias propriedades (
place
ename
)Exclusivo por todas as propriedades (isso será lento para matrizes grandes)
Mantenha a última ocorrência.
fonte
Um revestimento usando Set
Explicação:
new Set(myData.map(JSON.stringify))
cria um objeto Set usando os elementos myData com string.fonte
Usando o ES6 + em uma única linha, você pode obter uma lista exclusiva de objetos por chave:
Pode ser colocado em uma função:
Aqui está um exemplo de trabalho:
Como funciona
Primeiro, o array é remapeado de forma que possa ser usado como entrada para um mapa.
o que significa que cada item da matriz será transformado em outra matriz com 2 elementos; a chave selecionada como primeiro elemento e o item inicial inteiro como segundo elemento, isso é chamado de entrada (por exemplo , entradas de matriz , entradas de mapa ). E aqui está o documento oficial com um exemplo mostrando como adicionar entradas de matriz no construtor Map.
Exemplo quando a chave é local :
Em segundo lugar, passamos esse array modificado para o construtor Map e aqui está a mágica acontecendo. O mapa eliminará os valores das chaves duplicadas, mantendo apenas o último valor inserido da mesma chave. Nota : O mapa mantém a ordem de inserção. ( verifique a diferença entre mapa e objeto )
Terceiro, usamos os valores do mapa para recuperar os itens originais, mas desta vez sem duplicatas.
E o último é adicionar esses valores em uma nova matriz nova, para que ela possa parecer a estrutura inicial e retornar isso:
fonte
id
. A questão precisa que o objeto inteiro seja único em todos os campos comoplace
ename
Aqui está outra opção para fazê-lo usando os métodos de iteração Array, se você precisar comparar apenas um campo de um objeto:
fonte
um forro está aqui
fonte
Se você pode esperar para eliminar as duplicatas até depois de todas as adições, a abordagem típica é classificar primeiro a matriz e depois eliminar as duplicatas. A classificação evita a abordagem N * N de varrer a matriz para cada elemento à medida que você os percorre.
A função "eliminar duplicatas" geralmente é chamada de única ou uniq . Algumas implementações existentes podem combinar as duas etapas, por exemplo, o uniq do protótipo
Este post tem poucas idéias para tentar (e outras para evitar :-)) se sua biblioteca ainda não tiver uma ! Pessoalmente, acho este o mais direto:
fonte
function(_a,_b){return _a.a===_b.a && _a.b===_b.b;}
, a matriz não será classificada.A maneira mais simples é usar
filter
:fonte
id
. A questão precisa que o objeto inteiro seja único em todos os campos comoplace
ename
Esta é uma maneira genérica de fazer isso: você passa uma função que testa se dois elementos de uma matriz são considerados iguais. Nesse caso, ele compara os valores das propriedades
name
eplace
dos dois objetos que estão sendo comparados.Resposta ES5
Resposta original do ES3
fonte
Para adicionar mais um à lista. Usando ES6 e
Array.reduce
comArray.find
.Neste exemplo, filtrando objetos com base em uma
guid
propriedadeEstendendo este para permitir a seleção de uma propriedade e compactá-lo em um liner:
Para usá-lo, passe uma matriz de objetos e o nome da chave que você deseja desduplicar como um valor de sequência:
fonte
Você também pode usar um
Map
:Amostra completa:
Resultado:
fonte
Dang, crianças, vamos esmagar essa coisa, por que não?
fonte
id
. A questão precisa que o objeto inteiro seja único em todos os campos comoplace
ename
place
ename
hoje. Qualquer pessoa que esteja lendo este encadeamento está procurando uma maneira ideal de deduzir uma lista de objetos, e é uma maneira compacta de fazer isso.Uma solução TypeScript
Isso removerá objetos duplicados e também preservará os tipos dos objetos.
fonte
Considerando
lodash.uniqWith
fonte
Outra opção seria criar uma função indexOf personalizada, que compara os valores da propriedade escolhida para cada objeto e envolva-a em uma função de redução.
fonte
lodash.isequal
pacote npm como um comparador leve de objetos para executar uma filtragem de matriz exclusiva ... por exemplo, matriz distinta de objetos. Apenas trocados emif (_.isEqual(a[i], b)) {
vez de olhar @ uma única propriedadeUma linha usando ES6 e
new Map()
.Detalhes: -
.map()
na lista de dados e convertendo cada objeto individual em uma[key, value]
matriz de pares (comprimento = 2), o primeiro elemento (chave) seria astringified
versão do objeto e o segundo (valor) seria umobject
próprio.new Map()
teria a chave comostringified
objeto e qualquer mesma adição de chave resultaria na substituição da chave já existente..values()
daria ao MapIterator todos os valores em um mapa (obj
no nosso caso)spread ...
operador para fornecer uma nova matriz com valores da etapa acima.fonte
Aqui está uma solução para es6, na qual você deseja manter apenas o último item. Esta solução é funcional e compatível com o estilo Airbnb.
fonte
removeDuplicates () recebe uma matriz de objetos e retorna uma nova matriz sem nenhum objeto duplicado (com base na propriedade id).
Resultado esperado:
Primeiro, configuramos o valor da variável uniq para um objeto vazio.
Em seguida, filtramos a matriz de objetos. O filtro cria uma nova matriz com todos os elementos que passam no teste implementado pela função fornecida.
Acima, usamos a funcionalidade de curto-circuito do &&. Se o lado esquerdo do && for avaliado como true, ele retornará o valor à direita do &&. Se o lado esquerdo for falso, ele retornará o que está no lado esquerdo do &&.
Para cada objeto (obj), checamos uniq para uma propriedade denominada valor de obj.id (nesse caso, na primeira iteração, verificaria a propriedade '1'.) Queremos o oposto do que ele retorna (verdadeiro ou false) e é por isso que usamos o! in! uniq [obj.id]. Se o uniq já tiver a propriedade id, ele retornará true, que será falso (!), Dizendo à função de filtro NÃO para adicionar esse objeto. No entanto, se não encontrar a propriedade obj.id, retornará false, que será avaliado como true (!) E retornará tudo à direita de &&, ou (uniq [obj.id] = true). Este é um valor verdadeiro, dizendo ao método de filtro para adicionar esse obj à matriz retornada e também adiciona a propriedade {1: true} ao uniq. Isso garante que qualquer outra instância obj com o mesmo ID não seja adicionada novamente.
fonte
fonte
Eu acredito que uma combinação de
reduce
comJSON.stringify
para comparar perfeitamente objetos e seletivamente adicionar aqueles que ainda não estão no acumulador é uma maneira elegante.Lembre-se de que isso
JSON.stringify
pode se tornar um problema de desempenho em casos extremos em que a matriz possui muitos objetos e eles são complexos, mas, na maioria das vezes , esse é o caminho mais curto a seguir.Outra maneira de escrever o mesmo (mas menos eficiente):
fonte
Continuando a explorar as maneiras do ES6 de remover duplicatas da matriz de objetos: definir o
thisArg
argumento deArray.prototype.filter
paranew Set
fornece uma alternativa decente:No entanto, ele não funcionará com funções de seta
() =>
, poisthis
está vinculado ao seu escopo lexical.fonte
es6 magia em uma linha ... legível por isso!
fonte
Solução simples com os métodos auxiliares de matriz 'reduzir' e 'localizar' do ES6
Funciona com eficiência e perfeitamente bem!
fonte
Se você não se importa em classificar sua matriz única posteriormente, esta seria uma solução eficiente:
Dessa forma, você só precisa comparar o elemento atual com o elemento anterior na matriz. Classificar uma vez antes de filtrar (
O(n*log(n))
) é mais barato do que procurar uma duplicata em toda a matriz para cada elemento da matriz (O(n²)
).fonte
É uma maneira simples de remover a duplicidade da matriz de objetos.
Eu trabalho muito com dados e isso é útil para mim.
imprimirá no console:
fonte
str é uma matriz de objetos. Existem objetos com o mesmo valor (aqui um pequeno exemplo, existem dois objetos com o mesmo item_id que 2). check (id) é uma função que verifica se algum objeto com o mesmo item_id existe ou não. se existir, retorne false, caso contrário retorne true. De acordo com esse resultado, coloque o objeto em uma nova matriz obj. A saída do código acima é
[{"item_id":1},{"item_id":2}]
fonte
Você já ouviu falar da biblioteca Lodash? Eu recomendo esse utilitário, quando você realmente não deseja aplicar sua lógica ao código e usar o código já presente, otimizado e confiável.
Considere criar uma matriz como esta
Observe que, se você quiser manter um atributo exclusivo, poderá muito bem fazer isso usando a biblioteca lodash. Aqui, você pode usar _.uniqBy
Este método é como _.uniq (que retorna uma versão sem duplicação de uma matriz, na qual apenas a primeira ocorrência de cada elemento é mantida), exceto que ele aceita o iteratee que é chamado para cada elemento na matriz para gerar o critério pelo qual a exclusividade é calculada.
Portanto, por exemplo, se você deseja retornar uma matriz com atributo exclusivo de 'place'
Da mesma forma, se você deseja um atributo exclusivo como 'nome'
Espero que isto ajude.
Felicidades!
fonte