Как искать / фильтровать / сопоставлять типы с помощью динамически создаваемого многомерного массива

#javascript #ecmascript-6

#javascript #ecmascript-6

Вопрос:

Я пытаюсь выполнить поиск / фильтровать многомерный массив, который различается по количеству измерений (поскольку он представляет файловое дерево) по его name значению с помощью метода ES6 filter, но изо всех сил пытаюсь также вернуть вложенные объекты.

Как выглядит массив:

 const fileHierarchy = [
  {
    name: 'folder1',
    children: [
        { name: 'file1.txt' },
        { name: 'file2.txt' },
        {
            name: 'child folder1',
            children: [
                {
                    name: 'child folder2',
                    children: [
                        { name: 'file3.txt' },
                        { name: 'file4.txt' }
                    ]
                },
                { name: 'file5.txt' },
                { name: 'file6.txt' },
                {
                    name: 'child folder3',
                    children: [
                        { name: 'file7.txt' },
                        { name: 'file8.txt' }
                    ]
                }
            ]
        }
    ]
  },
  {name: 'folder2'}
]
  

Это то, что я уже пробовал (и как выглядит мой массив / объект):

 let currentFileHierarchy;
let searchString = 'file5';

currentFileHierarchy = fileHierarchy.filter(function (item) {
    return item.name.toLowerCase().indexOf(searchString.toLowerCase()) >= 0 
});
  

Результат currentFileHierarchy является только одномерным (доступен для поиска только folder1 и folder2 ), но он также должен включать все вложенные объекты, которые соответствуют строке поиска.

Если есть способ управлять этим, возможно ли также поддерживать структуру массива? Или мне нужно сначала его сгладить?

Ответ №1:

Сначала выровняйте массив, чтобы получить список имен:

 function flatten(names, arr) {
  arr.forEach((item) => {
    names.push(item.name);
    if (item.children) {
      flatten(names, item.children);
    }
  });
  return names;
}

var results = [];
flatten(results, fileHierarchy);

// 'results' has all the names now
  

Используйте results массив для фильтрации.

Комментарии:

1. У меня есть Lodash и я попробовал связанный подход, но после выравнивания данного массива с помощью const result = _.flatMap(fileHierarchy, ({ name, children }) => _.map(children, children => ({ name, ...children })) ); я получаю нечетный результат только из 3 объектов массива.

2. подождите, дайте мне проверить

3. @MangoD проверьте мой ответ сейчас.

4. @MangoD ты проверил?

5. Спасибо! Сейчас выглядит неплохо. Единственное, что осталось, это то, что мне нужно поддерживать хотя бы структуру объекта. Например. {name: 'file1.txt'} . Потому что, вероятно, будет добавлено больше ключей {name: 'file1.txt', format: 'txt'} .