Вложенный JSON найти элемент

0

У меня есть действующий JSON. Он описывает структуру дерева:

{
"items": [
    {
        "id": "d1"
    },
    {
        "id": "2",
        "children": [
            {
                "id": "3"
            },
            {
                "id": "4"
            },
            {
                "id": "5",
                "children": [
                    {
                        "id": "6"
                    },
                    {
                        "id": "7",
                        "children": [
                            {
                                "id": "8"
                            },
                            {
                                "id": "9"
                            }
                        ]
                    },
                    {
                        "id": "10"
                    }
                ]
            },
            {
                "id": "11"
            },
            {
                "id": "12"
            }
        ]
    },
    {
        "id": "13"
    },
    {
        "id": "14"
    }
]
}

Мне нужно получить любой из "элементов" по id и любому из дочерних элементов. Например. Первоначально я пробовал grep:

var returnedData = $.grep(obj.items, function(element, index){return element.id == "2";
});

Это отлично работает для элемента с id == 2, но полностью не удается, когда я пытаюсь получить element.id == "7"

Любая помощь будет оценена. Заранее спасибо.

Теги:

3 ответа

4
Лучший ответ

Вы можете сделать рекурсивную функцию для поиска в данных:

function find(source, id)
{
    for (key in source)
    {
        var item = source[key];
        if (item.id == id)
            return item;

        // Item not returned yet. Search its children by recursive call.
        if (item.children)
        {
            var subresult = find(item.children, id);

            // If the item was found in the subchildren, return it.
            if (subresult)
                return subresult;
        }
    }
    // Nothing found yet? return null.
    return null;
}

// In the root object, the array of items is called 'items', so we pass in 
// data.items to look into. The root object itself doesn't seem to have an id anyway.
var result = find(data.items, 7);

// Show the name of item 7, if it had one... 
alert(result.name);

Демо: http://jsfiddle.net/rj26H/

В этой функции я просто зациклился на объекте, поэтому он немного более подробный. Возможно, вы также можете использовать $.grep для выполнения поиска и сделать код немного меньше. Во всяком случае, трюк заключается в поиске всех детей, если элемент не найден на основном уровне. По-видимому, grep не работает рекурсивным образом.

  • 0
    Благодаря внешнему виду это выглядит хорошо. Нужно проверить в контексте моего сценария, но очень ценю ваш быстрый ответ.
  • 0
    @GolezTrol Это действительно странно. У меня отлично работает: jsfiddle.net/rj26H/4
Показать ещё 3 комментария
1

Попробуй это:

var id = 7;
var data = {"items": [{"id": "d1"},{"id": "2","children": [{"id": "3"},{"id": "7"},{"id": "11"},{"id": "12"}]}]};
function search(values) {
    $.each(values, function(i, v) {
        if (v.id == id) { 
           console.log('found', v);
           return false;
        }
        if (v.children) {
            search(v.children);
        }
    });
}
search(data.items);

Демо-ссылка

  • 0
    Это не потому, что это пример того, как это делает foo или bar подходящими именами.
  • 0
    Имя функции @plalx изменено
Показать ещё 2 комментария
0

Я знаю, что это уже ответили, но я хотел показать, как вы могли бы использовать новые функции JavaScript 1.7 для решения этой проблемы. Обратите внимание, что такой же подход можно было бы использовать без поддержки генераторов, но код был бы длиннее.

//Returns an iterator that knows how to walk a tree
function treeIterator(root, childGetter, childCountGetter) {
    let stack = [root], node;

    while (node = stack.pop()) {
        yield node;

        for (let i = childCountGetter(node); i--;) stack.push(childGetter(node, i));
    }
}

//Our custom search function
function findNodeById(tree, id) {
    let it = treeIterator(tree, 
        function (node, i) { return node.children[i]; },
        function (node) { return node.children? node.children.length : 0; }
    );

    for (let node in it) if (node.id === id) return node;

    return null;
}

var tree = {
    id: 'root',
    children: [
        { id: 'a' },
        {
            id: 'b',
            children: [
                { id: 'b1' },
                { id: 'b2' }
            ]
        },
        { id: 'c' }
    ]
};

findNodeById(tree, 'b1'); //Object { id="b1"}

Обратите внимание, что вы также можете установить __iterator__ в структуре данных, чтобы функции, которые необходимо перебирать по этой структуре данных, не должны были знать детали реализации.

tree.__iterator__ = treeIterator.bind(null, tree, 
    function (node, i) { return node.children[i]; },
    function (node) { return node.children? node.children.length : 0; }
);

Тогда функция findNodeById может быть:

function findNodeById(tree, id) {
    for (let node in it) if (node.id === id) return node;
    return null;
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню