How to get list of all child elements with field from parent
Asked Answered
A

2

11

I have list of dicts that contains another list in one of fields. I want to "flatten" that list, so it gives me every subelement with one field (or some fields) from parent copied into it. Example:

Source data:

[
    {
        "name": "A",
        "foo": "x",
        "bar": 1,
        "subelements": [
            {
                "baz": "xyz",
                "foobar": "abc"
            },
            {
                "baz": "zzz",
                "foobar": "def"
            }
        ]
    },
    {
        "name": "B",
        "foo": "Y",
        "bar": 4,
        "subelements": [
            {
                "baz": "yyy",
                "foobar": "aaa"
            },
            {
                "baz": "xxx",
                "foobar": "bbb"
            },
            {
                "baz": "www",
                "foobar": "bbb"
            }
        ]
    }
]

Expected result:

[
    {
        "baz": "xyz",
        "foobar": "abc",
        "foo": "x"
    },
    {
        "baz": "zzz",
        "foobar": "def",
        "foo": "x"
    },
    {
        "baz": "yyy",
        "foobar": "aaa",
        "foo": "Y"
    },
    {
        "baz": "xxx",
        "foobar": "bbb",
        "foo": "Y"
    },
    {
        "baz": "www",
        "foobar": "bbb",
        "foo": "Y"
    }
]
Artima answered 6/10, 2018 at 20:19 Comment(1)
what have you got so far?Cormac
M
5

This is not currently possible to do without parent node reference. Parent node access is still listed as a feature request

Malony answered 16/10, 2018 at 10:29 Comment(1)
Thanks! I was afraid that this is the case.Artima
C
-1

Do you have to use JMESPath? It's not complicated to do this in Vanilla JS:

ans = [];
input.forEach(elem =>
    elem["subelements"].forEach(subElem => {
        ans.push(Object.assign({
            foo: a["foo"]
        }, subElem))
    })
);

Or, if you like a little more FP,

ans = Array.prototype.concat.apply([], input.map(elem =>
    elem["subelements"].map(subElem =>
        Object.assign({
            foo: a["foo"]
        }, subElem)
    )
));

If you're serverside with ECMAScript 2018 or are polyfilling it, then you can replace Object.assign({foo: a["foo"]}, elem) with {foo: a["foo"], ...elem}. ECMAScript 2015 lets you do [].concat(...input.map(_)) for the second solution.

Copyread answered 16/10, 2018 at 21:18 Comment(1)
The problem is - it is not in javascript. I'm using some external tool where it is not possible to use anything else.Artima

© 2022 - 2024 — McMap. All rights reserved.