Как отфильтровать 2 массива объектов и эффективно их обработать? - PullRequest
0 голосов
/ 10 ноября 2018

У меня есть 2 массива объектов разных типов с разными комбинациями клавиш. Как выполнить эффективное сопоставление и обновление объекта для кода ниже? Я пробовал разные комбинации с .filter, но пока безуспешно. Я обновляю временный masterList на основе selectionList.

for (let selObj of selctionList) {
    for (let obj of masterList) {

        if (selObj['n'] == obj['name']) {
            obj['checked'] = true;
            obj['cost'] = selObj['r'];
            obj['qty'] = (selObj['q'] ? selObj['q'] : 1);
            break;
        }
    }
}
for (let obj of masterList) {
    if (!obj['checked']) {
        obj['checked'] = false;
    }
}

Пример данных

`masterList = 
[{"id":459,"cost":250,"name":"Coke"},
{"id":460,"cost":60,"name":"Cookies"},
{"id":461,"cost":100,"name":"Pizza"},
{"id":462,"cost":250,"name":"Bread"},
{"id":463,"cost":150,"name":"Sausage"},
{"id":464,"cost":150,"name":"Juice"}];
selectionList = [{"q":1,"r":350,"n":"Coke"}
{"q":2,"r":550,"n":"Bread"}]`

Выход:

`[{"id":459,"cost":350,"name":"Coke", "checked" : true,"qty":1},
{"id":460,"cost":60,"name":"Cookies","checked" : false},
{"id":461,"cost":100,"name":"Pizza","checked" : false},
{"id":462,"cost":550,"name":"Bread","checked" : true,"qty":2},
{"id":463,"cost":150,"name":"Sausage","checked" : false},
{"id":464,"cost":150,"name":"Juice","checked" : false}]`

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Функциональное решение, использующее lodash keyBy для ускорения расчета.

const masterList = [{"id":459,"cost":250,"name":"Coke"}, {"id":460,"cost":60,"name":"Cookies"}, {"id":461,"cost":100,"name":"Pizza"}, {"id":462,"cost":250,"name":"Bread"}, {"id":463,"cost":150,"name":"Sausage"}, {"id":464,"cost":150,"name":"Juice"}];
const selectionList = [{"q":1,"r":350,"n":"Coke"},{"q":2,"r":550,"n":"Bread"}];

const selectionMap = _.keyBy(selectionList, "n");
const output = masterList.map(masterItem => {
  // loop through the master list, see if we have it selected.
  const selectItem = selectionMap[masterItem.name];
  if(selectItem === undefined){
    // If it is not checked, return that information.
    return {
      ...masterItem,
      checked: false
    };
  }
  // if it is checked, return checked: true and the quantity info which defaults to 1.
  return {
    ...masterItem,
    checked: true,
    qty: selectItem['q'] || 1
  };
});

console.log(output);

Выход:

[[object Object] {
  checked: true,
  cost: 250,
  id: 459,
  name: "Coke",
  qty: 1
}, [object Object] {
  checked: false,
  cost: 60,
  id: 460,
  name: "Cookies"
}, [object Object] {
  checked: false,
  cost: 100,
  id: 461,
  name: "Pizza"
}, [object Object] {
  checked: true,
  cost: 250,
  id: 462,
  name: "Bread",
  qty: 2
}, [object Object] {
  checked: false,
  cost: 150,
  id: 463,
  name: "Sausage"
}, [object Object] {
  checked: false,
  cost: 150,
  id: 464,
  name: "Juice"
}]
0 голосов
/ 10 ноября 2018

Вы можете повысить эффективность времени этого кода с O (n²) до O (n) , используя хеш-карту для получения прямого доступа к masterList запись по названию:

const masterList = [{"id":459,"cost":250,"name":"Coke"}, {"id":460,"cost":60,"name":"Cookies"}, {"id":461,"cost":100,"name":"Pizza"}, {"id":462,"cost":250,"name":"Bread"}, {"id":463,"cost":150,"name":"Sausage"}, {"id":464,"cost":150,"name":"Juice"}];
const selectionList = [{"q":1,"r":350,"n":"Coke"},{"q":2,"r":550,"n":"Bread"}];

// Create a Map to key the masterList by name
const indexed = new Map(masterList.map(o => [o.name, o]));
// First init the checked property
for (const obj of masterList) obj.checked = false;
// Then iterate and lookup in the Map.
for (const {q, r, n} of selectionList) {
    const obj = indexed.get(n); // Lookup happens in constant time 
    if (!obj) continue;
    obj.cost = r;
    obj.qty = q || 1;
    obj.checked = true;
}

console.log(masterList);

NB. Кажется излишним хотеть хранить свойство checked, так как совпавшие объекты уже получают свойство qty, которого нет у других. В следующем коде вы можете легко проверить это с помощью:

checked = 'qty' in obj;
...