Reputation: 13
I have some data like these, because the nested object is hard to set state in redux, so I wanna to transform it as an object with id as key.So I can change state easily. I did a whole day search, but did not find a way
// here is the source data
// every object has an id property
// outer object has 2 or 3 levels: continents -> countries || continents -> countires -> regions
const source = [
{
id: 2,
name: "King",
continents: [
{
id: 12,
name: "Africa",
abbr: null,
countries: [
{
id: 13,
name: "South Africa",
abbr: "aa.jpg"
}
]
},
{
id: 5,
name: "European",
abbr: null,
countries: [
{
id: 7,
name: "France",
abbr: "fg.jpg"
}
]
},
{
id: 6,
name: "North America",
abbr: null,
countries: [
{
id: 8,
name: "Denmark",
abbr: "gg.jpg"
}
]
}
]
},
{
id: 1,
name: "Elite",
continents: [
{
id: 2,
name: "South America",
abbr: null,
countries: [
{
id: 4,
name: "Brazal",
abbr: "bx.jpg"
}
]
},
{
id: 5,
name: "European",
abbr: null,
countries: [
{
id: 9,
name: "England",
abbr: "yg.jpg",
regions: [
{
id: 1,
name: "England-1",
abbr: null,
},
{
id: 10,
name: "England-2",
abbr: null,
}
]
}
]
}
]
}
];
as you can see, every Object has an id
field.I wanna extract every id as key, output below:
// output
{
2: {
id: 2,
name: "King",
continents: {
12: {
id: 12,
name: "Africa",
countries: {
13: {
id: 13,
name: "South Africa"
}
}
},
6: {
id: 6,
name: "North America",
countries: {
8: {
id: 8,
name: "Denmark"
}
}
},
5: {
id: 5,
name: "European",
countries: {
7: {
id: 7,
name: "France"
}
}
}
}
},
1: {
id: 1,
name: "Elite",
continents: {
2: {
id: 2,
name: "South America",
countries: {
4: {
id: 4,
name: "Brazal"
}
}
},
5: {
id: 5,
name: "European",
countries: {
9: {
id: 9,
name: "England",
regions: {
1: {
id: 1,
name: "England-1"
},
2: {
id: 2,
name: "England-2"
}
}
}
}
}
}
}
}
I think I should use recursive or something, I even try with ramda.js,but still got no luck!
Upvotes: 0
Views: 108
Reputation: 138257
Create a function to turn arrays into lookup objects:
const toLookup = (array, key) => array.reduce((obj, el) => (obj[ el[key] ] = el, obj), {});
Then another one to traverse and map all nested properties:
function traverse (mapper, root) {
const result = {};
for(let [k, v] of Object.entries(root)) {
v = mapper(v, k);
if(typeof v === "object" && !Array.isArray(v) && v !== null)
v = traverse(mapper, v);
result[k] = v;
}
return result;
}
Now use that and turn every array into a lookup object:
const result = traverse(
it => Array.isArray(it) ? toLookup(it, "id") : it,
toLookup(source, "id")
);
Upvotes: 2