Lodash обновляет коллекцию, где

#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;
}));  

Надеюсь, это поможет.