Underscore: _.union не работает с массивами объектов

Созданный на 2 окт. 2015  ·  32Комментарии  ·  Источник: jashkenas/underscore

_.union всегда будет создавать дубликаты при передаче массивов объектов.

например, _.union( [ { a:1 } ], [ { a:1 } ]) вернет [ { a:1 }, { a:1 } ]

И наоборот, собственная функция isEqual подчеркивания скажет вам, что рассматриваемые объекты равны. Может быть, мы могли бы иметь флаг / параметр, который диктует использование сравнения на равенство, или возможность передать компаратор?

Самый полезный комментарий

Этот поток вдохновил меня на добавление _.intersectionWith , _.differenceWith , _.unionWith и _.uniqWith для обработки настройки сравнения в моем собственном коде.

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 }]

Все 32 Комментарий

Я удивлен, что он еще не поддерживает функцию сравнения. : +1:

Стоит отметить, что это относится ко всем другим функциям вычисления массивов, таким как разница, пересечение, уникальность и т. Д.

Было бы неплохо, если бы можно было обновить полный набор функций массива, чтобы разрешить использование другого компаратора равенства для объектов.

Не было бы проще, если бы у нас была опция, сравнивающая равенство на основе логического значения параметра, которое можно было бы передать в функцию _.union ()? Если это правда, он автоматически сравнивает все объекты в этом массиве.

Например, _.union([1, 2, 3, 10, [{a:1}, {a:1}]], true) , выведет [1,2,3,10, {a:1}]

@ amiral84 Нет. Это не связано. Если вы хотите такого поведения, скомпонуйте union с помощью flatten.

@michaelficarra Тогда я упустил суть этой темы? : D

@ amiral84 Похоже так. Запрос функции полностью и лаконично объясняется в первом комментарии.

основная проблема, похоже, заключается в _.uniq поскольку _.union - это просто функция-оболочка для unique и flatten.

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

Этот поток вдохновил меня на добавление _.intersectionWith , _.differenceWith , _.unionWith и _.uniqWith для обработки настройки сравнения в моем собственном коде.

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 }]

или что-то вроде _.isCollection чтобы определить, имеете ли вы дело с коллекцией. При работе с коллекцией при сравнении следует использовать _.isEqual вместо === что бесполезно в случае коллекции.

@dperrymorrow

следует использовать _.isEqual вместо === что бесполезно в случае коллекции.

Динамическое переключение звучит как плохая идея. JS для многих вещей использует сравнения === или SameValueZero . Если есть необходимость выйти за рамки этих сравнений, подойдет что-нибудь вроде _.uniqWith .

Спасибо за этот @jdalton , функции

@jdalton - хороший

Разве следующее не решит запрос @ wilhen01 _ (хотя и более подробный, чем хотелось бы) _

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

Разве следующее не решит запрос @ wilhen01 (хотя и более подробный, чем хотелось бы)

_.uniq уже поддерживает это.

верно, это моя точка зрения, приведенный выше код в настоящее время работает так, как опубликовано.
не могли бы вы просто вызвать uniq / unique с ключом к результату объединения?

@dperrymorrow Подумайте немного за пределами этого примера и добавьте еще одно свойство .

хорошо, понял, извини ... Я не пытаюсь вести себя агрессивно, просто хотел полностью разобраться в проблеме. Я бы с удовольствием отправил запрос на перенос функции _.uniqWith .

Не беспокойтесь, это было бы здорово.

_.intersectionWith, _.differenceWith, _.unionWith и _.uniqWith

Разве не было бы более приятным API, если бы функция сравнения могла быть опционально передана в качестве последнего аргумента вместо создания четырех новых функций?

@jashkenas

Разве не было бы более приятным API, если бы функция сравнения могла быть опционально передана в качестве последнего аргумента вместо создания четырех новых функций?

Да, это можно сделать, но есть сложности, потому что такие методы, как _.uniq уже поддерживают передачу итератора и сильно перегружены поддержкой двоичных / отсортированных флагов поиска и параметров контекста. Это означало бы ввести нюхание arity, которое кажется слишком умным для этой ситуации. Это также усложнило бы будущие усилия по модуляции, потому что он объединяет множество дополнительных функций в одну точку, когда реализации можно упростить и разделить на отдельные методы.

Верно, совершенно досадная проблема с дизайном. Но создание новых функций только для компаратора тоже не кажется правильным решением.

Хорошо, тогда дополнительные параметры функции сравнения - это путь сюда?
Если да, я могу обновить свой пулреквест.

единственная сложная часть, которую я предвижу, - это сделать парсинг параметров более сложным, как упомянутое выше

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

Возможно, добавив дополнительную проверку, чтобы увидеть, является ли isSorted _.isFunction рассматривать его как компаратор.

@jashkenas

Но создание новых функций только для компаратора тоже не кажется правильным решением.

Возможно, это лучший вариант в плохой ситуации. Недавно я решил разделить перегруженные функции и остался очень доволен результатом. Хотя он увеличивает поверхность API, он позволяет упростить реализацию и группировку аналогичных тематических методов, таких как maxBy , uniqBy , pickBy или uniqWith , unionWith , zipWith или sortedIndexBy , sortedIndexOf , sortedUniq . В случае uniq хотя я все еще использую общую базовую функцию в данный момент.

обновили этот запрос на перенос # 2368, спасибо.

Я: +1: за uniqBy или uniqWith . Я был бы категорически против дальнейшей перегрузки uniq (поскольку в настоящее время предлагается # 2368)

: +1: @megawac , uniqBy .

Fwiw lodash будет использовать uniqBy в качестве разделенной формы _.uniq(array, iteratee) и _.uniqWith в качестве формы для настройки компаратора.

Да, если подумать, uniqWith - лучшее имя

тогда мне следует вытащить запрос на Lodash с помощью отдельного метода?
Я думал, что два проекта объединились, я ошибаюсь?

@dperrymorrow

я должен вытащить запрос на Lodash с помощью отдельного метода, тогда

Нет необходимости, они уже находятся в основной ветке lodash.

Я думал, что два проекта объединились, я ошибаюсь?

Еще нет. Lodash v4 подтверждает некоторые идеи слияния.

@jdalton Не могли бы вы подробнее рассказать о реализации _.uniqWith с другими итераторами.

@Pavnii
Конечно. Вы можете проверить lodash / npm / _baseUniq .
Если comparator передается он использует arrayIncludesWith помощник делать чек вместо arrayIncludes (Подчеркивание - х contains ).

@jdalton Это мне помогает.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

arypbatista picture arypbatista  ·  3Комментарии

acl0056 picture acl0056  ·  5Комментарии

chikamichi picture chikamichi  ·  8Комментарии

clouddueling picture clouddueling  ·  3Комментарии

markvr picture markvr  ·  3Комментарии