использование метода «различия» подчеркивания на массивах объектов
47522 просмотра
8 ответа
_.difference([], [])
этот метод работает хорошо, когда у меня есть данные типа примитива, как
var a = [1,2,3,4];
var b = [2,5,6];
и _.difference(a,b)
звонок возвращается[1,3,4]
но в случае, если я использую объект как
var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
var b = [{'id':1, 'value':10}, {'id':4, 'value':40}];
не похоже на работу
Автор: Nas Источник Размещён: 12.11.2019 09:55Ответы (8)
15 плюса
Причина в том, что объекты с одинаковым содержимым не являются одинаковыми объектами, например
var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
a.indexOf({'id':1, 'value':10})
Он не вернет 0, а -1, потому что мы ищем другой объект
См. Исходный код http://underscorejs.org/underscore.js , _.difference
использует_.contains
_.difference = function(array) {
var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
return _.filter(array, function(value){ return !_.contains(rest, value); });
};
и в _.contains
конечном итоге использует, indexOf
следовательно, не найдет объекты, если они не указывают на один и тот же объект.
Вы можете улучшить подчеркивание _.contains
, просматривая все элементы и вызывая обратный вызов сравнения, который вы должны быть в состоянии передать разнице или содержать функцию, или вы можете проверить эту версию, которая улучшает методы содержит
55 плюса
попробуйте это для размера, чтобы найти разницу в массиве объектов:
var test = [{a: 1},{b: 2}];
var test2 = [{a: 1}];
_.filter(test, function(obj){ return !_.findWhere(test2, obj); });
Автор: kontr0l
Размещён: 23.10.2013 04:39
30 плюса
Хотя принятый ответ является правильным, а другие ответы также дают хорошие идеи, есть дополнительная опция, которую довольно легко реализовать с помощью подчеркивания.
Это решение основывается на том, что каждый объект имеет уникальный идентификатор, но во многих случаях это будет так, и вы сможете получить разницу двух массивов объектов всего в двух строках кода.
Используя метод «pluck» подчеркивания, вы можете быстро создать массив всех идентификаторов в вашем исходном наборе и целевом наборе. Оттуда все методы массива подчеркивания будут работать, различие, объединение, пересечение и т. Д.
После операции легко получить список объектов из вашего исходного списка, который вы хотите. Вот пример:
Подробный:
var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
var b = [{'id':1, 'value':10}, {'id':4, 'value':40}];
var arr1 = _.pluck(a, "id");
var arr2 = _.pluck(b, "id");
var diff = _.difference(arr1, arr2);
var result = _.filter(a, function(obj) { return diff.indexOf(obj.id) >= 0; });
или, более кратко:
var diff = _.difference(_.pluck(a, "id"), _.pluck(b, "id"));
var result = _.filter(a, function(obj) { return diff.indexOf(obj.id) >= 0; });
Конечно, эту же технику можно расширить для использования с любым из методов массива.
Автор: Clayton Gulick Размещён: 27.12.2013 08:453 плюса
Я действительно могу представить себе ситуации, в которых я предпочел бы использовать подход @ kontr0l, а не что-то еще, но вы должны понимать, что этот подход является квадратичным, поэтому в основном этот код является абстракцией для наивного подхода - перебирайте все значения в двух массивах.
Есть подходы лучше, чем квадратичные, я не буду здесь использовать большие обозначения O, но вот два основных подхода, оба лучше, чем наивный:
- переберите один из массивов и проверьте наличие во втором отсортированном массиве с помощью бинарного поиска.
- положить значения в набор / хэш / словарь / вы называете это.
Как уже упоминалось, первый подход может быть принят для объектов, если вы переопределите стандартный difference
метод с использованием более гибкого аналога indexOf
метода.
При втором подходе мы можем столкнуться с тем фактом, что по состоянию на февраль 2015 года наборы поддерживаются только современными браузерами . Что касается хэшей (ну, объектов) в javascript, они могут иметь только ключи строкового типа, поэтому любой объект, вызываемый как ключ, сначала должен быть преобразован с помощью toString
метода. Итак, нам нужно предоставить некоторое => соответствие. На практике в большинстве случаев это довольно просто, например, для вашего конкретного примера такое соответствие может быть просто String(obj.id)
.
Имея такую корреспонденцию, мы также можем использовать следующий подход lodas / undercore:
var idsA = _.pluck(a, 'id');
var idsB = _.pluck(b, 'id');
// actually here we can stop in some cases, because
// quite often we need to identify object, but not the object itself -
// for instance to send some ids through remote API.
var intersect = _.intersection(idsA, idsB);
//to be 100% sure you get the idea, here we assume that object having equal ids are treated as equal, so does not really matter which of arrays we'll iterate:
var dictA = _.object(idsA, a); // now we can find a by id faster then with _.find
var intersectObj = intersect.map(function(id) {return dictA[id})
Но купите, допустив чуть более строгое ограничение - мы можем построить соответствие между нашими объектами множества и натуральными числами, мы можем построить еще более эффективный алгоритм, то есть все наши идентификаторы неотрицательные целые числа - мы можем использовать более эффективный алгоритм.
Хитрость заключается в том, чтобы реализовать set, введя два вспомогательных массива следующим образом:
var naturalSet = function (arr) {
var sparse = [];
var dense = [];
var contains = function (i) {
var res = sparse[i] < dense.length && dense[sparse[i]] == i;
return res;
}
var add = function (v) {
if (!contains(v)) {
sparse[v] = dense.length;
dense.push(v);
}
}
arr.forEach(add);
return {
contains: contains,
toArray: function () {
return dense
},
_getDense: function () {
return dense
},
_getSparse: function () {
return sparse
}
}
}
Затем мы можем ввести множество с отображением в NaturalSet:
var set = function (arr, valueOf) {
var natSet = naturalSet(arr.map(valueOf));
return {
contains: function (item) {
return natSet.contains(valueOf(item))
},
toArray: function () {
var sparse = natSet._getSparse();
var res = natSet._getDense().map(function (i) {
return arr[sparse[i]];
});
return res;
}
}
}
и, наконец, мы можем ввести пересечение:
var intersection = function(arr1, arr2, valueOf) {
return set(arr2.filter(set(arr1, valueOf).contains), valueOf).toArray();
}
Таким образом, полагаясь на структуру данных, с которыми вы работаете, иногда вы можете помочь.
Автор: shabunc Размещён: 16.02.2015 12:083 плюса
without using underscorejs,
here is the pretty simple method i got solution ...
a = [{'key':'123'},{'key':'222'},{'key':'333'}]
b = [{'key':'123'},{'key':'222'}]
var diff = a.filter(function(item1) {
for (var i in b) {
if (item1.key === b[i].key) { return false; }
};
return true;
});
console.log('result',diff)
Автор: Mohideen bin Mohammed
Размещён: 29.12.2015 09:29
1 плюс
var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
var b = [{'id':1, 'value':10}, {'id':4, 'value':40}];
var c = _.difference(a.map(e => e.id), b.map(e =>e.id));
var array = [];
array = a.map(e => {
if(c.includes(e.id)){
return e;
}
}).filter(r=>r);
Автор: Anirudh
Размещён: 12.04.2018 06:46
0 плюса
Простите, что прыгнул в конце здесь, но это может помочь:
array_of_objects =
// return the non-matching items (without the expected properties)
_.difference(array_of_objects,
// filter original list for items with expected properties
_.where(
// original list
array_of_objects,
// expected properties
{'id':1, 'value':10}
)
)
Автор: Gauss156
Размещён: 17.02.2014 07:21
0 плюса
Не понимаю, почему эти ответы такие сложные, если я что-то упустил?
var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
var b = [{'id':1, 'value':10}, {'id':4, 'value':40}];
// Or use lodash _.differenceBy
const difference = (array1, array2, prop = 'id') =>
array1.filter(item1 =>
!array2.some(item2 =>
item2[prop] === item1[prop],
),
);
// In one array.
console.log(difference(a, b));
// Intersection.
console.log([...difference(a, b), ...difference(b, a)]);
Вопросы из категории :
- javascript Как определить, какой из указанных шрифтов был использован на веб-странице?
- javascript Валидация клиентской стороны ASP.Net
- javascript Длина объекта JavaScript
- javascript Получение текста из выпадающего списка
- javascript Скрипт входа со скрытыми кнопками
- javascript Как автоматически изменить размер текстовой области с помощью Prototype?
- javascript Удаление элементов с помощью Array.map в JavaScript
- javascript Прокрутка переполненных DIV с помощью JavaScript
- javascript API Карт Google - проблемы с классом GLatLngBounds
- javascript Проверка десятичных чисел в JavaScript - IsNumeric ()
- underscore.js Отладка шаблонов underscore.js затруднена без номеров строк
- underscore.js RequireJS и текстовый плагин Время ожидания загрузки для модулей
- underscore.js Удаление дублирующихся объектов с помощью Underscore для Javascript
- underscore.js Сортировка по дате с underscore.js или просто простой JS
- underscore.js Underscore.js: создать карту из списка объектов, используя ключ, найденный в объекте
- underscore.js do <something> N раз (декларативный синтаксис)
- underscore.js Можно ли получить индекс, по которому вы сортируете, в Underscore.js?
- underscore.js Подчеркни js найти предмет по ID
- underscore.js Выход из тега <% -%> в шаблоне underscore.js
- underscore.js Суммируйте данные, используя .countBy