2

I have a bunch of content in an array with type:

export interface StaticContent {
  level : number,
  id : string,  
  title: string,
  content : string[] | StaticContent[],
}

I'm trying to search for an object where id to query is a sub-element to a content object. I think I've probably set the interface up wrong but I'm having a mental block.

Any ideas?

Example:

data = [
{
  level: 0,
  id: 'first-element',
  title: 'Title of the first element'
  content: [
    `I am some random string of content`
  ]
},
{
  level: 1,
  id: 'second-element',
  title: 'Title of the second element'
  content: [
     {
       level: 0,
       id: 'first-sub-element',
       title: 'Title of first sub element'
       content: [
         ` I am some content attached to the first sub element `
       ]
     }
}]

let idToFind = 'first-sub-element'
let element = data.find(t => t.id === idToFind)
let title = element.title

In this example the result is an undefined element.
I expect

element = {
       level: 0,
       id: 'first-sub-element',
       title: 'Title of first sub element'
       content: [
         ` I am some content attached to the first sub element `
       ]
     }
}
5
  • what is wrong withnyoue code? what result are you expecting? Commented Jan 13, 2022 at 18:49
  • in the above example I will get an element that is undefined. I expect to receive the whole first element in the content array from the second element. Commented Jan 13, 2022 at 18:51
  • please add the expected result in your post Commented Jan 13, 2022 at 18:54
  • data doesn't have an element with id=first-sub-element. array.find only looks in the first level array. Commented Jan 13, 2022 at 18:58
  • I need a method that searches the nested elements as well Commented Jan 13, 2022 at 18:59

2 Answers 2

4

You need to use recursion or do a recursive search in place.

Here is recursion example:


function searchInContent(idToFind: string, content: StaticContent[] | string[]): StaticContent | null {   
    for (const c of content) {
       if (typeof c === 'string') continue
 
       // now we can assume that c is StaticContent
       if (c.id === idToFind) {
          // FOUND RESULT
          return c
       } 
   
       // Perform deep search in content
       const result = searchInContent(idToFind, c.content)
       if (result !== null) {
          // stop searching and pass found result
          return result
       }
    }
    return null
}

let idToFind = 'first-sub-element'
let element = searchInContent(data)
let title = element.title

Sign up to request clarification or add additional context in comments.

1 Comment

Great! A minor mistake, searchInContent(data) is missing the idToFind parameter.
1

You are trying to find the content object for a specific id. What you could do is flatMap() the contents and then use find() to find the correct matching object.

const data = [{
    level: 0,
    id: 'first-element',
    title: 'Title of the first element',
    content: [
      `I am some random string of content`
    ]
  },
  {
    level: 1,
    id: 'second-element',
    title: 'Title of the second element',
    content: [{
      level: 0,
      id: 'first-sub-element',
      title: 'Title of first sub element',
      content: [
        ` I am some content attached to the first sub element `
      ]
    }, {
      level: 0,
      id: 'first-sub-elemeeent',
      title: 'Title of first sub element',
      content: [
        ` I am some content attached to the first sub element `
      ]
    }]
  }
];

const idToFind = 'first-sub-element';
const result = data.flatMap(d => d.content).find(c => c.id === idToFind);

console.log(result);

3 Comments

what about cases where you have multiple nested elements. For example if I'm searching for 'second-sub-element' (assuming it exists)
this would not work in the case where I want to grab something off the parent now right? example 'first-element'
@ShaunLangley updated the answer, trick was first mapping the contents and then running a find on the outcome array

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.