1

I have an array and want to get just object { id: 4, name: 'name4' },

const example = [
    {
      id: '1234',
      desc: 'sample1',
      items: [
        { id: 1, name: 'name1' },
        { id: 2, name: 'testItem2' }
       ]
      },    
    {
        id: '3456',
        desc: 'sample2',
      items: [
         { id: 4, name: 'name4' },
         { id: 5, name: 'testItem5' }
       ]
    },

I try in this way.

const name = 'name4';
example.forEach((item) => item.items.find((i) => i.name === name));

But get undefined.

1

4 Answers 4

3

You can using flatMap() to do it

const example = [
    {
      id: '1234',
      desc: 'sample1',
      items: [
        { id: 1, name: 'name1' },
        { id: 2, name: 'testItem2' }
       ]
      },    
    {
        id: '3456',
        desc: 'sample2',
        items: [
         { id: 4, name: 'name4' },
         { id: 5, name: 'testItem5' }
       ]
    }]
    
const name = 'name4';
let result = example.flatMap(e => e.items).filter(d => d.name == name)
console.log(result)

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

1 Comment

Wow. I never bothered to read what .flatMap does and now I regret my life choices. (It's been available since 2015). What a useful method this is.
2

this way...?

const example = 
  [ { id   : '1234'
    , desc : 'sample1'
    , items: 
      [ { id: 1, name: 'name1'     } 
      , { id: 2, name: 'testItem2' } 
    ] } 
  , { id   : '3456'
    , desc : 'sample2'
    , items: 
      [ { id: 4, name: 'name4'     } 
      , { id: 5, name: 'testItem5' } 
  ] } ]; 

const rechName = (s,arr) => 
  arr.find( x =>         // find the first parent object
    x.items.some( y =>  // containing the search
     y.name === s )
   )?.items                       // if one
     .find( z => z.name === s ); // find it in!

console.log( rechName('name4', example) ) // -> { id: 4, name: 'name4' }
console.log( rechName('abc', example) )  // -> undefined

1 Comment

I like this better, because this avoids collecting all the items into one massive array.
2

forEach doesn't do what you think it does. From the docs:

The forEach() method executes a provided function once for each array element.

...

Return value
undefined.

So if you want to use forEach you need to save the value:

const example = 
  [ { id   : '1234'
    , desc : 'sample1'
    , items: 
      [ { id: 1, name: 'name1'     } 
      , { id: 2, name: 'testItem2' } 
    ] } 
  , { id   : '3456'
    , desc : 'sample2'
    , items: 
      [ { id: 4, name: 'name4'     } 
      , { id: 5, name: 'testItem5' } 
  ] } ] 
  
const results = []; // Store matches here

const name = 'name4';
example.forEach((item) => {
  const res = item.items.find((i) => i.name === name);
  if (res !== undefined) {
    results.push(res);
  }
});

console.log(results);

IMHO I would suggest a more functional approach using flatMap and filter instead of forEach.

Lastly, note that in my above snippet, I'm storing the results in an array as it's not entirely clear to me that you won't have multiple matches per your example. But if you're sure that you will only ever have one result then a simple for loop works better, especially if you have a large array of items:

let result = null;
for (let i = 0; i < example.length; i++) {
  const res = example[i].items.find((j) => j.name === name);
  if (res !== undefined) {
    result = res;
    break; // No need to iterate further
  }
}
console.log(result);

Comments

1

You could use a recursive search function. Here's a detailed example:

// Applies the function recursively from the top of the data tree ("depth-first")
const
  data = getData(),
  id = 4,
  result = findById(data, id);
console.log(result ?? `No item with id ${id} found`);

// Defines the function
function findById(haystack, needleId){
  let needle = null; // Defaults to null if no match at or below this level

  // Iterates through all the items at this level
  for(const item of haystack){
    if(item.id == needleId){
      // Qapla': Quits early, passes honorable item up to previous level
      needle = item;
      return needle;
    }
    else {
      // Checks children, grandchildren, etc, before continuing iteration
      const nextHaystack = item.items;
      if(nextHaystack?.length){
        needle = findById(nextHaystack, needleId); // Recursive call
      }
    }
    // Done searching children, continues to next iteration at this level
  }
  // Done searching this level, returns result up to previous level
  return needle;
}

// Gets the initial data
function getData(){
  return [
    {
      id: '1234',
      desc: 'sample1',
      items: [ { id: 1, name: 'name1' }, { id: 2, name: 'testItem2' } ]
    },
    {
      id: '3456',
      desc: 'sample2',
      items: [ { id: 4, name: 'name4' }, { id: 5, name: 'testItem5' } ]
    }
  ];
}

Comments

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.