0

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!

1 Answer 1

2

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")
);
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much! You're a genius. You saved my day!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.