iremlopsum
iremlopsum

Reputation: 187

How to merge nested objects with the same key

I'm having a hard time merging nested objects with potentially the same key using Object.assign();

See code as an example

// Initial structure
let state = {
    pageIndex: 1,
    allResults: {
        queries: {}
    }
}

Code

const assign = (query, page) => {
    const obj = {
        [page]: {
            res: 'hi'
        }
    }

    state.allResults.queries = Object.assign(
        {},
        state.allResults.queries,
        state.allResults.queries[query] || {[query]: {}},
        obj
    )
}

assign('hi', state.pageIndex);
assign('hi', (state.pageIndex + 1));
assign('hello', (state.pageIndex + 1));

console.log(state)

What I'm getting

state = {
    pageindex: 1,
    allResults: {
        queries: {
            1: {
                res: 'hi'
            },
            2: {
                res: 'hi'
            },
            hello: {},
            hi: {}
        }
    }
}

What I expect

let state = {
    pageIndex: 1,
    allResults: {
        queries: {
            hi: {
                1: {
                    res: 'h'
                },
                2: {
                    res: 'h'
                }
            },
            hello: {
                2: {
                    res: 'h'
                }
            }
        }
    }
}

So, this the way how I'm doing it doesn't really work, and I can't figure out how to get the expected result.

Thanks in advance

Upvotes: 2

Views: 116

Answers (3)

Bamse
Bamse

Reputation: 493

This will assign the desired sub key of the queries key which you send to the assign function (hi or hello) to their previous value, combined with the new value.

state.allResults.queries[query] = Object.assign(
    {},
    state.allResults.queries[query] || {},
    obj
)

Upvotes: 2

I think this could work for you:

const assign = (query, page) => {
    const obj = {
        [page]: {
            res: 'hi'
        }
    }

    let _obj = Object.assign(
        {},
        state.allResults.queries[query] || {},
        obj
    );

    state.allResults.queries = Object.assign(
        {},
        state.allResults.queries,
        { [query]: _obj }
    )
}

First I created the plain object that will be assigned to the subQuery object. Then I merge it into a existing (if not, {} an empty) object.

After that I just merge that into the query object.

Hope that it helps you.

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386560

You could use a nested Object.assign.

const assign = (query, page) => {
    const obj = { [page]: { res: 'hi' } }
    state.allResults.queries = Object.assign(
        {},
        state.allResults.queries,
        { [query]: Object.assign(state.allResults.queries[query] || {}, obj) }
    );
}

let state = { pageIndex: 1, allResults: { queries: {} } };

assign('hi', state.pageIndex);
assign('hi', (state.pageIndex + 1));
assign('hello', (state.pageIndex + 1));

console.log(state)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions