0

I naively wrote the following function thinking it would help me find an object which is deep down in a data structure. But this wont work due to the return being scoped within a foreach. The function will always return undefined. How should I be doing this?

const findStuff = (data, x) => {
    data.forEach(u => {
        u.userData.forEach(ud => {
            const s = ud.stuff.find(s=>s.id === x.id);
            if (s){
                return s;
            }
        });
    });
};
Baz
  • 12,713
  • 38
  • 145
  • 268

3 Answers3

1

I think your approach is wrong. That's...to much code. I've made an object that seems to conform to the data you are looking through:

var data = [
  {
    username: "Alice",
    userData : [
      {
        id: 1,
        someData: "hello"
      },
      {
        id: 2,
        someData: "world"
      }
    ]
  },
  {
    username: "Bob",
    userData : [
      {
        id: 3,
        someData: "apple"
      },
      {
        id: 4,
        someData: "orange"
      }
    ]
  }
];

const findStuff = (data, lookup) => {
  return data.find(
    item => item.userData.some(
      userDataItem => userDataItem.id === lookup.id
    )
  );
}

const shouldGetAlice     = findStuff(data, {id: 1});
const shouldBeAliceAgain = findStuff(data, {id: 2});
const shouldGetBob       = findStuff(data, {id: 3});
const shouldBeAnotherBob = findStuff(data, {id: 4});

console.log(shouldGetAlice.username);
console.log(shouldBeAliceAgain.username);
console.log(shouldGetBob.username);
console.log(shouldBeAnotherBob.username);

Start off with .find() because you want to get a single item.

Inside the callback, you use .some() to check the userData properties, instead of looping through them yourself.

And that's it. You don't need to manually loop through each array.

If the descriptive variable names are removed, the function can be shortened to

const findStuff = (data, x) => {
   return data.find(u => u.userData.some(ud => ud.id === x.id));
}

It can also be written on one line but it seems less clear.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
0

Use a variable at the top of your closure, and return that after the forEach.

const findStuff = (data, x) => {
    let found;

    data.forEach(u => {
        u.userData.forEach(ud => {
            const s = ud.stuff.find(s=>s.id === x.id);
            if (s){
                found = s;
            }
        });
    });

    return found;
};
romellem
  • 5,792
  • 1
  • 32
  • 64
0

You could use Array#some and end the iteration with returning true. You need a variable for the found value.

const findStuff = (data, x) => {
    let found;

    data.some(u => 
        u.userData.some(ud => {
            const s = ud.stuff.find(s => s.id === x.id);
            if (s) {
                found = s;
                return true;
            }
        })
    );
    return found;
};
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392