Интересно, есть ли в lodash более простой метод для замены элемента в коллекции JavaScript? (Возможен дубликат, но я там не понял ответа :)
Я просмотрел их документацию, но ничего не нашел
Мой код:
var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];
// Can following code be reduced to something like _.XX(arr, {id:1}, {id:1, name: "New Name"});
_.each(arr, function(a, idx){
if(a.id === 1){
arr[idx] = {id:1, name: "Person New Name"};
return false;
}
});
_.each(arr, function(a){
document.write(a.name);
});
Обновление: объект, который я пытаюсь заменить, имеет много свойств, например
{id: 1, Prop1: ..., Prop2: ... и так далее}
Решение:
Благодаря dfsq, но я нашел подходящее решение в lodash, которое, кажется, работает нормально и довольно аккуратно, и я также поместил его в миксин, поскольку это требование есть во многих местах. JSBin
var update = function(arr, key, newval) {
var match = _.find(arr, key);
if(match)
_.merge(match, newval);
else
arr.push(newval);
};
_.mixin({ '$update': update });
var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];
_.$update(arr, {id:1}, {id:1, name: "New Val"});
document.write(JSON.stringify(arr));
Более быстрое решение Как указано в @dfsq, следующее намного быстрее
var upsert = function (arr, key, newval) {
var match = _.find(arr, key);
if(match){
var index = _.indexOf(arr, _.find(arr, key));
arr.splice(index, 1, newval);
} else {
arr.push(newval);
}
};
javascript
lodash
Вишал Сет
источник
источник
_.findIndex
на матч._.findIndex
вместо_.find
позволит вам отбросить и второй,_.find
и_.indexOf
. Вы повторяете массив 3 раза, когда все, что вам нужно, это 1.Ответы:
В вашем случае все, что вам нужно сделать, это найти объект в массиве и использовать
Array.prototype.splice()
метод, подробнее читайте здесь :источник
indexOf
оно будет очень быстрым (оно будет использовать собственные браузеры Array.prototype.indexOf). Но в любом случае рад, что вы нашли решение, которое работает для вас._.findIndex
? Тогда вам не нужно пользоваться_.indexOf
.Похоже, самым простым решением было бы использовать ES6
.map
или lodash_.map
:Это дает хороший эффект, позволяющий избежать изменения исходного массива.
источник
[ES6] Этот код работает у меня.
источник
updatedItem
массив if, который не включает элемент с таким жеid
.Теперь проверим производительность всех методов:
Показать фрагмент кода
источник
Вы также можете использовать findIndex и pick для достижения того же результата:
источник
По прошествии времени вы должны принять более функциональный подход, в котором вы должны избегать мутаций данных и писать небольшие функции с единственной ответственностью. С стандартом ECMAScript 6, вы можете наслаждаться функциональной парадигмой программирования в JavaScript прилагаемой
map
,filter
иreduce
методе. Вам не нужен еще один lodash, подчеркивание или что-то еще, чтобы делать самые простые вещи.Ниже я включил некоторые предлагаемые решения этой проблемы, чтобы показать, как эту проблему можно решить с помощью различных языковых функций:
Используя карту ES6:
Рекурсивная версия - эквивалент отображения:
Требуется деструктуризация и распространение массива .
Когда последний порядок массива не важен, вы можете использовать его
object
как структуру данных HashMap . Очень удобно, если у вас уже есть коллекция с ключамиobject
- в противном случае вам сначала нужно изменить свое представление.Требуется разброс остатков объекта , вычисленные имена свойств и объекты Object.entries .
источник
Если вы просто пытаетесь заменить одно свойство, достаточно lodash
_.find
и_.set
:источник
Если точка вставки нового объекта не обязательно должна совпадать с индексом предыдущего объекта, тогда самый простой способ сделать это с помощью lodash - использовать,
_.reject
а затем вставить новые значения в массив:Если у вас есть несколько значений, которые вы хотите заменить за один проход, вы можете сделать следующее (написано в формате, отличном от ES6):
источник
Используя функцию lodash unionWith, вы можете выполнить простое обновление до объекта. В документации указано, что если есть совпадение, он будет использовать первый массив. Оберните обновленный объект в [] (массив) и поместите его как первый массив функции объединения. Просто укажите логику сопоставления, и если она будет найдена, она заменит ее, а если нет, то добавит.
Пример:
источник
Тоже неплохой вариант)
источник
источник
Если вы ищете способ неизменяемого изменения коллекции (как и я, когда нашел ваш вопрос), вы можете взглянуть на immutability-helper , библиотеку, созданную на основе оригинальной утилиты React. В вашем случае вы бы выполнили то, что упомянули, следующим образом:
источник
Вы можете сделать это без использования lodash.
источник
Неизменяемый , подходит для
ReactJS
:Предполагать:
Обновленный элемент является вторым, и его имя изменено на
Special Person
:Подсказка : в lodash есть полезные инструменты, но теперь у нас есть некоторые из них на Ecmascript6 +, поэтому я просто использую
map
функцию, которая существует на обоихlodash
иecmascript6+
:источник
С этим тоже наткнулся и сделал это просто так.
При желании мы можем обобщить это
источник