简体   繁体   中英

Reduce javascript array with nested children

I'm trying to create a help page for a website using mongodb and graphql. I've made this schema (joiGoose Schema) for the help pages:

constructor()
{
    const joiSchema = joi.object
    ({
        url: joi.string().required(),
        title: joi.string().required(),

        content: joi.string().required(),

        children: joi.array().items
        (
            joi.string().meta({ _mongoose: { type: "ObjectId", ref: "Help" } }).optional(),
        ).meta({ _mongoose : { _id: false, timestamps: false } }),

        published: joi.boolean().default(true).required(),

        createdAt: joi.date().required().default(() => moment()),
        updatedAt: joi.date().required().default(() => moment()),
    });
        
    const mongooseSchema = super(joigoose.convert(joiSchema));
    return mongooseSchema;
}

The first thing I want to do is to give the summary of the help section. I get all the pages from mongodb using the following query:

const allHelpPages = await MONGO.Help.find();`

It gives me an array containing all the help pages. As each page can have multiple nested children pages (there is no maximum level), what I need is to reduce the array with the children for all the pages.

Example:

const allPages = 
[
    {
        id: 1,
        title: Test 1,
        children:
        [
            2,
            3
        ]
    },
    {
        id: 2,
        title: Test 2,
        children:
        [
            4,
            5
        ]
    }
    {
        id: 3,
        title: Test 3,
        children:
        [
            6
        ]
    }
    {
        id: 4,
        title: Test 4
    }
    {
        id: 5,
        title: Test 5
    }
    {
        id: 6,
        title: Test 6,
        children:
        [
            7
        ]
    }
    {
        id: 7,
        title: Test 7
    }
]

Should end to:

[
    {
        id: 1,
        title: Test 1,
        children:
        [
            {
                id: 2,
                title: Test 2,
                children:
                [
                    {
                        id: 4,
                        title: Test 4
                    },
                    {
                        id: 5,
                        title: Test 5
                    }
                ]
            },
            {
                id: 3,
                title: Test 3,
                children:
                [
                    {
                        id: 6,
                        title: Test 6,
                        children:
                        [
                            {
                                id: 7,
                                title: Test 7
                            }
                        ]
                    }
                ]
            }
        ]
    },
]

You could create one object that you can use as a lookup table where keys are ids of objects. And then based on that object you can modify children arrays with actual objects and in the end just filter out objects that are children of some other object.

 const data = [{"id":1,"title":"Test 1","children":[2,3]},{"id":2,"title":"Test 2","children":[4,5]},{"id":3,"title":"Test 3","children":[6]},{"id":4,"title":"Test 4"},{"id":5,"title":"Test 5"},{"id":6,"title":"Test 6","children":[7]},{"id":7,"title":"Test 7"}] const map = {}, isChild = {} for (let o of data) { map[o.id] = o } const result = Object.entries(map).map(([k, v]) => { const children = v.children; if (children) children.forEach((id, i) => { isChild[id] = true children[i] = map[id] }) return {...v, children} }).filter(({ id }) =>.isChild[id]) console.log(result)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM