Underscore: _.union não funciona com matrizes de objetos

Criado em 2 out. 2015  ·  32Comentários  ·  Fonte: jashkenas/underscore

_.union sempre produzirá duplicatas quando forem passados ​​arrays de objetos.

por exemplo, _.union( [ { a:1 } ], [ { a:1 } ]) retornará [ { a:1 }, { a:1 } ]

Perversamente, a função isEqual do próprio sublinhado informará que os objetos em questão são iguais. Talvez pudéssemos ter um sinalizador / opção que dita a comparação de igualdade a ser usada, ou a opção de passar um comparador?

change

Comentários muito úteis

Este tópico me inspirou a adicionar _.intersectionWith , _.differenceWith , _.unionWith e _.uniqWith para lidar com a personalização de comparação em meu próprio código.

var array = [ { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }, { 'a': 1, 'b': 2 } ];

_.uniqWith(array, _.isEqual);
// => [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }]

Todos 32 comentários

Estou surpreso que ainda não aceite a função de comparação. : +1:

É importante ressaltar que isso se aplica a todas as outras funções de computação de array, como diferença, interseção, único, etc.

Seria bom se o conjunto completo de funções de matriz pudesse ser atualizado para permitir o uso de um comparador de igualdade diferente para objetos.

Não seria mais fácil se tivéssemos uma opção que compara a igualdade com base no valor do parâmetro booleano que pode ser passado para a função _.union ()? Se for verdade, ele irá comparar automaticamente todos os objetos nessa matriz.

Por exemplo, _.union([1, 2, 3, 10, [{a:1}, {a:1}]], true) , produziria [1,2,3,10, {a:1}]

@ amiral84 Não. Isso não está relacionado. Se você deseja esse comportamento, componha união com achatar.

@michaelficarra Então eu perdi o objetivo desse tópico? : D

@ amiral84 Parece que sim. A solicitação de recurso é explicada completa e sucintamente no primeiro comentário.

o problema subjacente parece estar em _.uniq pois _.union é meramente uma função de empacotamento para exclusivo e nivelado.

_.union = restArgs(function(arrays) {
  return _.uniq(flatten(arrays, true, true));
});

Este tópico me inspirou a adicionar _.intersectionWith , _.differenceWith , _.unionWith e _.uniqWith para lidar com a personalização de comparação em meu próprio código.

var array = [ { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }, { 'a': 1, 'b': 2 } ];

_.uniqWith(array, _.isEqual);
// => [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }]

ou algo parecido com _.isCollection para determinar se você está lidando com uma coleção. Se estiver lidando com uma coleção, então as comparações devem usar _.isEqual vez de === que não adianta no caso de uma coleção.

@dperrymorrow

deve usar _.isEqual vez de === que não adianta no caso de uma coleção.

A comutação dinâmica parece uma má ideia. JS usa === ou SameValueZero comparações para muitas coisas. Se houver necessidade de ir além dessas comparações, algo como _.uniqWith faria.

Obrigado por este @jdalton , as funções _opWith que você mencionou são absolutamente perfeitas para o que estou tentando alcançar. Alguma ideia de quando eles estarão disponíveis via lançamento?

@jdalton é uma boa observação sobre as comparações, mas você normalmente não usaria uma chave de exclusividade em uma coleção em vez de forçar o sublinhado para detectar toda a diferença entre os objetos?

O seguinte não resolveria a solicitação de @ wilhen01 _ (embora mais prolixo do que o desejado) _

_.chain([{ a: 1 }]).union( [{a: 1}]).unique('a').value();
//=> [{a: 1}]

O seguinte não resolveria a solicitação de @ wilhen01 (embora mais prolixo do que o desejado)

_.uniq já suporta isso.

certo, esse é o meu ponto, o código acima funciona conforme postado.
você não poderia simplesmente chamar uniq / unique com uma chave no resultado da união?

@dperrymorrow Pense um pouco fora desse exemplo e adicione outra propriedade .

ok, entendi, desculpe ... Não estou tentando ser beligerante, só queria entender totalmente o problema. Eu adoraria enviar uma solicitação de pull na função _.uniqWith .

Não se preocupe, isso seria demais.

_.intersectionWith, _.differenceWith, _.unionWith e _.uniqWith

Não seria uma API melhor permitir apenas que a função de comparação fosse opcionalmente passada como o argumento final, em vez de cunhar quatro novas funções?

@jashkenas

Não seria uma API melhor permitir apenas que a função de comparação fosse opcionalmente passada como o argumento final, em vez de cunhar quatro novas funções?

Sim, isso poderia ser feito, mas há complicações porque métodos como _.uniq já suportam a passagem de um iteratee e estão muito sobrecarregados com suporte para sinalizadores de pesquisa binários / classificados e parâmetros de contexto também. Isso significaria introduzir uma cheirada de aridade, que parece muito inteligente para esta situação. Isso também complicaria os esforços de modularização futuros porque agrupa muitas funcionalidades opcionais em um único ponto, quando as implementações poderiam ser simplificadas e divididas em métodos separados.

Certo, um problema de design totalmente infeliz. Mas criar novas funções apenas para permitir um comparador também não parece a solução certa.

ok, então, parâmetros de função de comparação adicionais são o caminho a percorrer aqui?
Nesse caso, posso atualizar minha solicitação de pull.

a única parte complicada que prevejo é tornar a análise de parâmetro um pouco mais complicada, como @jdalton mencionado acima.

_.uniq = _.unique = function(array, isSorted, iteratee, context) {
  if (!_.isBoolean(isSorted)) {
    context = iteratee;
    iteratee = isSorted;
    isSorted = false;
  }
//...

Talvez adicionando uma verificação adicional para ver se isSorted _.isFunction e trate-o como o comparador.

@jashkenas

Mas criar novas funções apenas para permitir um comparador também não parece a solução certa.

Pode ser a melhor opção para uma situação ruim. Eu comecei a dividir funcionalidades sobrecarregadas recentemente e estou muito feliz com o resultado. Embora aumente a superfície da API, permite implementações mais simples e agrupamento de métodos com temas semelhantes, como maxBy , uniqBy , pickBy ou uniqWith , unionWith , zipWith , ou sortedIndexBy , sortedIndexOf , sortedUniq . No caso de uniq embora eu ainda use uma função de base compartilhada no momento.

atualizei esta solicitação pull # 2368, obrigado.

Eu sou: +1: para uniqBy ou uniqWith . Eu seria totalmente contra sobrecarregar uniq ainda mais (como # 2368 é proposto atualmente)

: +1: @megawac , uniqBy .

Fwiw Lodash usará uniqBy como a forma de divisão de _.uniq(array, iteratee) e _.uniqWith como a forma para permitir a personalização do comparador.

Sim, pensando bem, uniqWith é um nome melhor

devo puxar a solicitação no Lodash com o método separado então?
Pensei que os dois projetos se fundissem, estou enganado?

@dperrymorrow

devo puxar o pedido no Lodash com o método separado, então

Não há necessidade, eles já estão no branch master de borda de Lodash.

Pensei que os dois projetos se fundissem, estou enganado?

Ainda não. O Lodash v4 prova algumas das ideias da fusão, no entanto.

@jdalton Você pode elaborar um liitle mais sobre a implementação de _.uniqWith com outro iteratee.

@Pavnii
Certo. Você pode verificar lodash / npm / _baseUniq .
Se um comparator for passado, ele usa arrayIncludesWith auxiliar para fazer a verificação em vez de arrayIncludes (sublinhado contains ).

@jdalton Isso me ajuda.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

arypbatista picture arypbatista  ·  3Comentários

acl0056 picture acl0056  ·  5Comentários

markvr picture markvr  ·  3Comentários

marcalj picture marcalj  ·  5Comentários

sky0014 picture sky0014  ·  8Comentários