Фильтровать выбранных детей из данных, используя Javascript - PullRequest
0 голосов
/ 13 ноября 2018

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

Но это работает только для 2 уровня. Я не понимаю, чего мне не хватает.

Данные, которые я хочу отфильтровать: </p> <pre><code> var data = [ { name: "john_pc", children: [ { name: "sabrina_pc", children: [ { name: "sabrina_pc" }, { name: "john_pc" } ] }, { name: "john_pc" } ] }, { name: "sabrina_pc" } ]

Функция childrenFilter:

const childrenFilter = (childrenData, filters) => {
    let filteredData = childrenData.filter(item => {
        for (var property in filters) {
            var optionalValues = filters[property];
            var value = item[property];
            if (item.children) {
                item.children = childrenFilter(item.children, filters);
            }
            let hasValue = value == optionalValues;
            if (hasValue) {
                return true;
            }
            return false;
        }
        return false;
    }, this);
    return filteredData;
}

Вызов функции:

Как вы можете видеть, 'childrenFilter' получает объект, ключ которого является свойством данных, а ключ является значением, которое я хочу сохранить. let result = childrenFilter(data, { "name": "a1" }); console.log(JSON.stringify(result, null, 2))

Требуемый результат:

</p> <pre><code> [ { "name": "john_pc", "children": [ { "name": "sabrina_pc", "children": [ { "name": "john_pc" } ] }, { "name": "john_pc" } ] } ]

Ответы [ 2 ]

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

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

Этот подход генерирует новые объекты и не изменяет исходные данные.

function filter(array, filters) {
    return array.reduce((r, o) => {
        var children = filter(o.children || [], filters);
        return children || Object.entries(filters).every(([k, v]) => o[k] === v)
            ? (r || []).concat(Object.assign({}, o, children && { children }))
            : r;
    }, undefined);
}

var data = [{ name: "a1", children: [{ name: "a2", children: [{ name: "a2" }, { name: "a1" }] }, { name: "a1" }] }, { name: "b1" }];
    
console.log(filter(data, { name: "a1" }));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 13 ноября 2018

Ваша функция фильтра не учитывает, соответствуют ли дочерние элементы шаблону, поэтому даже если некоторые дочерние элементы объекта соответствуют шаблону, сам объект отфильтровывается.

Вотобъяснение:

        {
            name: "a2", // does not match filter {name:'a1} so is removed alongside child objects
            children: [ // gets removed with parent object
                {
                    name: "a2"
                },
                {
                    name: "a1" 
                }
            ]
        }

Это должно дать желаемый результат:

    const childrenFilter = (childrenData, filters) => {
    let filteredData = childrenData.filter(item => {
        for (var property in filters) {
            var optionalValues = filters[property];
            var value = item[property];
            if (item.children) {
                item.children = childrenFilter(item.children, filters);
            }
            let hasValue = value == optionalValues;
            if (hasValue || item.children.length) { // include item when children mathes the pattern
                return true;
            }
            return false;
        }
        return false;
    }, this);
    return filteredData;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...