Фильтрация вложенного массива объектов - es6 - PullRequest
0 голосов
/ 30 августа 2018

Ниже приведен массив объектов, и я пытаюсь отфильтровать только те объекты, которые имеют type:y. Как видите, массив объектов может также содержать вложенный массив той же схемы и может быть вложенным на N-уровне. Поэтому, пожалуйста, помогите мне с наиболее оптимизированной функцией ES6 для достижения этой цели.

[
    {
        name: 'a',
        type: 'x',
        array:
            [
                {   
                    name: 'l',
                    type: 'y',
                },
                {   
                    name: 'm',
                    type: 'y',
                },
                {   
                    name: 'n',
                    type: 'x',
                    array:
                        [
                            {   
                                name: 'x',
                                type: 'y',
                            },
                            {   
                                name: 'y',
                                type: 'y',
                            },
                            {   
                                name: 'z',
                                type: 'x',
                            }
                        ]
                }
            ]
    },
    {
        name: 'b',
        type: 'y',
    },
    {
        name: 'c',
        type: 'y',
    },

]

Также ниже приведен код, который я написал для достижения этой цели. ищет возможности улучшить производительность и оптимизировать ее

filterFunction(fields) { 
    const result = [];
    (fields || []).forEach((field) => { 
      if (field.array) {
        const x = field;
        x.array = this.filterFunction(field.array);
        result.push(x);
      } else if (field.type !== 'x') {
        result.push(field);
      }
    });
    return result;
  }

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Вы можете отфильтровать массив, используя Object.assign для новых объектов с более глубоко отфильтрованными массивами.

function filter(array, type) {
    return array.reduce((r, o) => {
        var array = filter(o.array || [], type);
        if (o.type === type || array.length) {
            r.push(Object.assign({}, o, { array }));
        }
        return r;
    }, []);
}

var array = [{ name: 'a', type: 'x', array: [{ name: 'l', type: 'y', }, { name: 'm', type: 'y', }, { name: 'n', type: 'x', array: [{ name: 'x', type: 'y', }, { name: 'y', type: 'y', }, { name: 'z', type: 'x', }] }] }, { name: 'b', type: 'y', }, { name: 'c', type: 'y' }];

console.log(filter(array, 'y'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 30 августа 2018

Вы можете использовать шаблон сгиба:

function walkRec(input, accumulator, state = []) {
  if (!(input instanceof Array)) input = [input];
  for (const item of input) {
    state = accumulator(item, state);
    const isObject = item !== null && typeof item == 'object';
    if (isObject && 'array' in item)
      state = walk(item.array, accumulator, state);
  }
  return state;
}

если дерево, которое вы должны отфильтровать, большое (много поддерева), вы можете получить ошибку «Превышен максимальный размер стека вызовов», и вы, вероятно, предпочтете такой тип итерации:

function walk(input, accumulator, state = []) {
  if (!(input instanceof Array)) input = [input];
  while (input.length > 0) {
    const item = input.shift();
    state = accumulator(item, state);
    const isObject = item !== null && typeof item == 'object';
    if (isObject && 'array' in item) {
      const children = item.array instanceof Array ? item.array : [item.array];
      Array.prototype.push.apply(input, children);
    }
  }
  return state;
}

и используйте его следующим образом

walk(array, (item, state) => {
  if (item && item.type == 'y')
    state.push(item)
  return state;
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...