-1

I have an arbitrarily deep nested array of objects, simplified here as:

interface IComponent {
  title: string;
  components?: IComponent[];
}

const data: IComponent[] = [
  {
    title: 'First Component',
    components: [
      {
        title: 'Nested Component 1',
        components: [
          {
            title: 'Child 1 of: Nested Component 1'
          },
          {
            title: 'Child 2 of: Nested Component 1'
          },
          {
            title: 'Child 3 of: Nested Component 1'
          }
        ]
      },
      {
        title: 'Nested Component 2',
        components: [
          {
            title: 'Child of: Nested Component 2'
          }
        ]
      }
    ]
  }
];

I have an array of the indexes in this nested array that point to one object to return:

const indexMap: number[] = [0, 0, 2];

Currently, I'm cheating by creating a string to eval as such:

let evalString = 'data';

indexMap.forEach((index: number, iterator: number) => {
  if (iterator === 0) {
    evalString += `[${ index }]`;
  }
  else {
    evalString += `.components[${ index }]`;
  }
});

Resulting in a string such as: data[0].components[0].components[2]

Which works, but I'd like to avoid using eval. I've tried a few variations using .reduce() but I seem to be stumbling over first getting data[index] and then accessing the components value.

Is there a better/simpler/safer way of getting to data[0].components[0].components[2] given this data structure?

This question: Index an array of arrays with an array of indexes in javascript is similar, but with a different data structure.

This question is also similar: Accessing nested JavaScript objects and arrays by string path but my root object has a slightly different data structure.

Brandon Taylor
  • 33,823
  • 15
  • 104
  • 144
  • `indexMap.slice(1).reduce(({ components }, index) => components[index], data[indexMap[0]])`? Or you could simplify the start with `indexMap.reduce(({ components }, index) => components[index], { components: data })`. This isn't really a [tag:typescript] question, this is just [tag:javascript]. – jonrsharpe Jan 27 '21 at 16:37
  • Wow @jonrsharpe - that's incredibly helpful, and now so obvious when I see it. Please add answer with your comment code and I'll gladly accept it. Thank you so much. I sincerely appreciate the help. – Brandon Taylor Jan 27 '21 at 16:41
  • Does this answer your question? [Accessing nested JavaScript objects and arrays by string path](https://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-and-arrays-by-string-path) – Heretic Monkey Jan 27 '21 at 16:45
  • @HereticMonkey that example is accessing properties of an object via string syntax. In my case, I have an array of objects and an array of indexes. – Brandon Taylor Jan 27 '21 at 16:47
  • "Resulting in a string such as: data[0].components[0].components[2] Which works, but I'd like to avoid using eval." – Heretic Monkey Jan 27 '21 at 16:48
  • Right, running `eval()` using that string is accessing the items by index, not dot-path – Brandon Taylor Jan 27 '21 at 16:49

1 Answers1

1

You can simplify the process by starting with an object where your data array is the components prop, then it's just a single .reduce over the indexMap:

indexMap.reduce(({ components }, index) => components[index], { components: data })
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437