2

I have an issue with flattening array.

Given that the structure is following

{
  "name": "Somename",
  "property": [
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      }
    ]
  ]
}

Or maybe better illustrated with this picenter image description here

How can I flatten matches into single array of objects or actually have flat structure where all nested items are in single array or object ?

I have managed to get so far by wrangling data but seem stuck at this I can use pretty much any library or tool and latest JS features.

I have tried mapping over values , reducing it using lodash deepMerge but cant seem to accomplish what I want.

Input:

const data = [
       {
        "sport": "Handball",
        "matches": [
            [
                {
                    "home": "Izmir BSB SK (Youth) (Wom)",
                    "away": "Bursa Osmangazi (Youth) (Wom)",
                    "ID": "3092996854"
                }
            ],
            [
                {
                    "home": "Al Muheet U21",
                    "away": "Al Mohmel U21",
                    "ID": "3092999932"
                }
            ]
        ]
    },
    {
        "sport": "Volleyball",
        "matches": [
            [
                {
                    "home": "Ji-Hee Choi/Michika Ozeki",
                    "away": "Panji Ahmad Maulana",
                    "ID": "3093062401"
                },
                {
                    "home": "Ryazan (Wom)",
                    "away": "Angara Irkutsk (Wom)",
                    "ID": "3093062393"
                }
            ],
            [
                {
                    "home": "CF Carthage (Wom)",
                    "away": "Winner - Broughton Excels",
                    "ID": "3093721823"
                }
            ],
            [
                {
                    "home": "Ankara Yildirim Beyazit Universitesi (Wom)",
                    "away": "Saglik Bilimleri Universitesi (Wom)",
                    "ID": "3093058567"
                }
            ]
        ]
    }
    ]

Expected output of each matches prop:

    {
      "sport": "Handball",
      "matches": [
        {home: '...', other: '...', id: '...'},
        {home: '...', other: '...', id: '...'},
        {home: '...', other: '...', id: '...'},
        {home: '...', other: '...', id: '...'},
      ]
    }
ukaric
  • 428
  • 1
  • 7
  • 22
  • 1
    What is your expected output? `[{.?.},{.?.}]` – Nope Mar 08 '18 at 14:45
  • { "name": "Somename", "property": [ {prop: 'someProp', other: 'otherProp'}, {prop: 'someProp', other: 'otherProp'}, {prop: 'someProp', other: 'otherProp'}, {prop: 'someProp', other: 'otherProp'} ] } – ukaric Mar 08 '18 at 14:47
  • if you want to get help, show us expected output – 0.sh Mar 08 '18 at 14:47
  • 2
    add it to your question – 0.sh Mar 08 '18 at 14:48
  • 1
    `Or maybe better illustrated with this pic` - nope. We hate pics ;/ – georg Mar 08 '18 at 14:48
  • 1
    @georg There was a pic? I can't see them,.. :/ - I guess that's why this might apply, even if it is not code per-se [**Why not to upload Images of Code when asking a Question**](https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-on-so-when-asking-a-question/285557#285557) - Also, who knows if that image-link is even there in 2 Month, making the question useless for future users if it is gone and the expected output isn't in the question. – Nope Mar 08 '18 at 14:49
  • I know i do but It would be hard explaining what I have and what I want to accomplish. – ukaric Mar 08 '18 at 14:49
  • Possible duplicate of [Merge/flatten an array of arrays in JavaScript?](https://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript) – user3297291 Mar 08 '18 at 15:01
  • It is similar but I have array of arrays that contains objects which are nested. – ukaric Mar 08 '18 at 15:03
  • What do you mean with *I have array of arrays that contains objects which are nested*? Can you post an example? – Ele Mar 08 '18 at 15:06

6 Answers6

4

You can use the function reduce and to check for array objects the function Array.isArray.

var data = {  "name": "Somename",  "property": [    [      {        "prop": "someprop",        "other": "someother"      },      {        "prop": "someprop",        "other": "someother"      }    ],    [      {        "prop": "someprop",        "other": "someother"      },      {        "prop": "someprop",        "other": "someother"      },      {        "prop": "someprop",        "other": "someother"      },      {        "prop": "someprop",        "other": "someother"      }    ],    [      {        "prop": "someprop",        "other": "someother"      }    ]  ]};

data.property = data.property.reduce((mapped, p) => 
                [...mapped, ...(Array.isArray(p) ? p : [p])], []);
//                                    ^
//                                    |
//                                    +- This is to check for situations where 
//                                       a particular object is not an array.

console.log(JSON.stringify(data, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ele
  • 33,468
  • 7
  • 37
  • 75
0

Use the spread operator and array.concat. array.concat has this unique condition where if the argument is an array, it adds the contents of that array to the result array instead of the array itself. The spread operator spreads the array's contents as args of the function, one after the other.

const flatProperties = [].concat(...data.property)

const data = {
  "name": "Somename",
  "property": [
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      }
    ]
  ]
}

const flatProperties = [].concat(...data.property)

console.log(flatProperties)
Joseph
  • 117,725
  • 30
  • 181
  • 234
0

You can use .reduce on your array

data.property = data.property.reduce(
  (acc, el) => acc.concat(el) , []
)

var data = {
  "name": "Somename",
  "property": [
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      }
    ]
  ]
};

data.property = data.property.reduce(
  (acc, el) => acc.concat(el) , []
)

console.log(data);
void
  • 36,090
  • 8
  • 62
  • 107
0

You can use concat and apply methods. This answer is similar to the answer by Joseph but without ES6 array spread operator

var originalArray = {
  "name": "Somename",
  "property": [
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      }
    ]
  ]
};

var flattened = [].concat.apply([],originalArray["property"]);
console.log(flattened)
mahan
  • 12,366
  • 5
  • 48
  • 83
0

If you are using lodash, this works too.

var data = {
  "name": "Somename",
  "property": [
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      }
    ]
  ]
}

data.property = _.flattenDeep(data.property)

console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
arunmmanoharan
  • 2,535
  • 2
  • 29
  • 60
  • I have to map over the original array and manipulate property that has nested array of objects I have tried lodash as well. – ukaric Mar 08 '18 at 15:00
0

you can use recursive function to traverse the array

const props = {
  "name": "Somename",
  "property": [
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      },
      {
        "prop": "someprop",
        "other": "someother"
      }
    ],
    [
      {
        "prop": "someprop",
        "other": "someother"
      }
    ]
  ]
};


function smoosh(populate) {
    return function _smoosh(arr) {
        if ( Array.isArray(arr) ) {
            for ( let value of arr ) {
                _smoosh(value);
            }
        }
        if ( typeof(arr) === "object" && ! Array.isArray(arr) ) {
            populate.push(arr);
        }
    };
}

const flatten = [];

smoosh(flatten)(props.property);

Object.assign(props,{
    property: flatten
});
console.log(props);
0.sh
  • 2,659
  • 16
  • 37