Скажем, оригинальная коллекция:

var data = [{
  id: 1,
  children: [{
    id: 2
  }, {
    id: 3
  }]
}, {
  id: 4,
  children: [{
    id: 5
  }]
}]

Хотите отфильтровать его с помощью заданных значений свойства id:

var selectedIds = [1, 3, 4]

Результаты должны быть:

var result = [{
  id: 1,
  children: [{
    id: 3
  }]
}, {
  id: 4,
  children: []
}]

Как сделать это, используя методы Lodash?

0
Jason Lam 26 Фев 2018 в 11:28

3 ответа

Лучший ответ

Вы можете использовать map и filter вместе, чтобы применить фильтр к вложенному элементу,

_.map(data, elem => {
    elem.children = _.filter(elem.children, child => selectedIds.includes(child.id));
    return elem;
});

ПРИМЕЧАНИЕ. Предполагается, что фильтр должен применяться только к свойству children.

Чтобы не изменять оригинал data,

_.map(data, elem => {
    let children = _.filter(elem.children, child => selectedIds.includes(child.id));
    return Object.assign({}, elem, {children});
});
1
RaR 26 Фев 2018 в 13:09

Вам нужно будет рекурсивно просмотреть свою коллекцию (и детей каждого элемента). Я не верю, что у lodash есть собственный способ реализации этого. Я написал функцию matcher, которая принимает коллекцию и выбранные идентификаторы, возвращает элементы, соответствующие этим идентификаторам, передает дочерние элементы и делает то же самое. Я не был уверен, как справиться с ситуацией, когда родитель не выбран, а дети ... Я просто предполагал, что вы выбросите их всех.

Дело в том, что у вас есть очень специфическая структура (элементы и дочерние элементы, которые являются элементами), которая требует от вас написания определенной рекурсивной функции, которая знает, как обходить эту структуру.

const matcher = (collection, selected) => _.reduce(collection, (result, item) => {

  if (selected.includes(item.id)) {
    result.push({
        id: item.id,
        children: matcher(item.children, selected)
    })
  }

  return result
}, [])

const result = matcher(data, selectedIds)
1
THEtheChad 26 Фев 2018 в 08:58

Вы можете проверить идентификатор и взять только детей с нужным идентификатором.

function getParts(array, ids) {
    return array.reduce((r, { id, children }) =>
        r.concat(ids.includes(id)
            ? { id, children: getParts(children || [], ids) }
            : []
        ), []);
}

var data = [{ id: 1, children: [{ id: 2 }, { id: 3 }] }, { id: 4, children: [{ id: 5 }] }];

console.log(getParts(data, [1, 3, 4]));
console.log(getParts(data, [1, 3, 5]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0
Nina Scholz 26 Фев 2018 в 09:13