Преобразовать объект JS - PullRequest
       10

Преобразовать объект JS

1 голос
/ 28 октября 2019

Я пытаюсь преобразовать этот объект:

[
    {
        "keyword":"apple",
        "category_1":"object",
        "category_2":"living",
        "category_3":"fruit",
        "count":5
    },
    {
        "keyword":"orange",
        "category_1":"object",
        "category_2":"living",
        "category_3":"fruit",
        "count":1
    },
    {
        "keyword":"table",
        "category_1":"object",
        "category_2":"non living",
        "category_3":"house item",
        "count":3
    },
    {
        "keyword":"cat",
        "category_1":"object",
        "category_2":"living",
        "category_3":"animal",
        "count":4
    },
    {
        "keyword":"stadium",
        "category_1":"place",
        "category_2":"sport related",
        "category_3":"indoor",
        "count":2
    }
]

в такой объект:

[
    {
        label: 'object',
        count: 9,
        childs: [
            {
                label: 'living',
                count: 6,
                childs: [
                    {
                        label: 'fruit',
                        count: 6,
                        childs: [
                            {
                                keyword: 'apple',
                                count: 5,
                            },
                            {
                                keyword: 'orange',
                                count: 1,
                            }
                        ]
                    }
                ]
            },
            {
                label: 'non living',
                count: 3,
                childs: [
                    {
                        label: 'animal',
                        count: 3,
                        childs: [
                            {
                                keyword: 'cat',
                                count: 3,
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        label: 'place',
        count: 2,
        childs: [
            {
                label: 'sport related',
                count: 2,
                childs: [
                    {
                        label: 'indoor',
                        count: 2,
                        childs: [
                            {
                                keyword: 'stadium',
                                count: 2,
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

Я пытался с Array.reduce рекурсивным способом, но у меня проблемыс рекурсивностью я всегда врезаюсь в стену. Как видите, суть в том, чтобы превратить массив во вложенный объект, сгруппировав его элементы по категориям (счетная часть не обязательна)

Если у кого-то есть какие-то мысли по этому вопросу

1 Ответ

2 голосов
/ 28 октября 2019

Вы можете сначала превратить данные во вложенные Карты, каждая из которых имеет соответствующую категорию. Это позволяет быстро определить правильную ветвь, в которую нужно внедрить следующий объект.

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

Код:

function makeTree(data) {
    // Create tree using nested Maps, keyed by category
    let main = new Map;
    for (let {keyword, category_1, category_2, category_3, count} of data) {
        let obj = { keyword, count };
        let map = main;
        for (let cat of [category_1, category_2, category_3]) {
            let child = map.get(cat);
            if (!child) map.set(cat, child = new Map);
            map = child;
        }
        let child  = map.get(keyword);
        if (!child) map.set(keyword, child = { keyword, count: 0 });
        child.count +=  count;
    }

    // Recursive function to turn the nested Maps into the target structure
    function transform(data) {
        let parentCount = 0;
        let arr = Array.from(data, ([label, value]) => {
            let count, children;
            if (value instanceof Map) {
                ([children, count] = transform(value));
                value = { label, count, children };
            } else {
                ({ count } = value);
            }
            parentCount += count;
            return value;        
        });
        return [arr, parentCount];
    }
    return transform(main)[0];
}

// Example run:
let data = [{"keyword":"apple","category_1":"object","category_2":"living","category_3":"fruit","count":5},{"keyword":"orange","category_1":"object","category_2":"living","category_3":"fruit","count":1},{"keyword":"table","category_1":"object","category_2":"non living","category_3":"house item","count":3},{"keyword":"cat","category_1":"object","category_2":"living","category_3":"animal","count":4},{"keyword":"stadium","category_1":"place","category_2":"sport related","category_3":"indoor","count":2}];

console.log(makeTree(data));
...