#javascript #lodash
#javascript #Lodash
Вопрос:
Допустим, у вас есть коллекция, подобная этой:
var sizes = [
{label: 'Small', instock: true, onsale: true},
{label: 'Medium', instock: false, onsale: true},
{label: 'Large', instock: false, onsale: true},
];
Обратите внимание, что коллекция здесь действительно проста для целей вопроса, но в реальном варианте использования объекты могут быть намного больше и сложнее и повторяться несколько раз (поэтому решение для этого должно быть максимально эффективным).
Мне нужно обновить запас всего, чего нет в наличии, до true. Вот что я пробовал до сих пор:
var index = _.findIndex(sizes, instock:false);
sizes[index].instock = true;
Но это обновляет только 1 элемент, в MySQL вы могли бы сделать что-то подобное в 1 строке кода, и я хочу попытаться выяснить, как сделать что-то подобное в Lodash или обычном Javascript (с 1 функцией или 1 строкой кода), потому что мне приходится делать подобные вещи довольно часто, и это становится чрезвычайно громоздким в обычном javascript, чтобы делать это с циклом, вручную перебирающим всю коллекцию.
Эквивалент MySQL был бы чем-то вроде:
UPDATE sizes instock=true WHERE instock=false
Я хочу сделать что-то подобное в Lodash или обычном Javascript, что бы ни было самым простым и эффективным.
Еще одна вещь, которую я пытаюсь выяснить, как это сделать, — это эквивалент MySQL.
UPDATE sizes onsale=false WHERE onsale=true AND instock=false
Комментарии:
1. Все библиотеки будут эффективно выполнять цикл над коллекцией.
Ответ №1:
Если вы просто хотите установить для instock
каждого объекта значение true, вы можете использовать простой цикл for
for(var i = 0; i < sizes.length; i ){
sizes[i].instock = true;
}
или с Lodash (что будет фактически тем же самым)
_.each(sizes, function (size){size.instock = true});
Обратите внимание, что здесь мы не проверяем значение instock
, потому что это не имеет значения. Если instock
равно true
, оно останется прежним, и если оно равно false, оно изменится. Проверка значения unstuck
стоит дороже, чем «ненужное» присвоение true
значения, которое уже истинно.
Для вашего второго оператора нам действительно нужно проверить значение instock
, но не onsale, как мы не проверяли значение instock в первом операторе.
_.each(sizes, function (size){
if(!instock) {
size.onsale = false;
}
});
Важно: я предполагаю, что значения переменной, которые я не проверял, никогда не равны null / undefined. Если они могут быть и в этом случае не должны изменяться, то вам все равно нужно добавить проверки.
Ответ №2:
Более эффективным способом решения вашей проблемы было бы использование простого for
цикла.
У вас могла бы быть вспомогательная функция для перехода по элементам массива. Эта вспомогательная функция могла бы получать функцию в качестве аргумента, которая выполняла бы проверку, чтобы обновить ключ объекта соответствующим значением. Таким образом, можно было бы эмулировать (очень простым способом) инструкцию SQL update.
var sizes = [{
label: 'Small',
instock: true,
onsale: true
}, {
label: 'Medium',
instock: false,
onsale: true
}, {
label: 'Large',
instock: false,
onsale: true
}, ];
function update(arr, key, transformFnc) {
var i = arr.length,
obj;
for (; i !== 0;) {
obj = arr[--i];
obj[key] = transformFnc(obj);
}
return arr;
}
console.log(update(sizes, 'instock', function(obj) {
// Returns true when instock is false -> is the same as putting all to true.
return true;
}));
console.log(update(sizes, 'onsale', function(obj) {
// Returns false when onsale=true AND instock=false, otherwise, doesn't do anything
return obj.onsale === true amp;amp; obj.instock === false ? false : obj.onsale;
}));
Надеюсь, это поможет.