2

I have the following nested objects in an array and i want to filter the result to return the id of a specific item.

const data = [
   {0: {id: 1, country: "SA", address: "IOXX"}},
   {1: {id:2, country: "SAP", name: "N", address: "IOP"}},
   {2: {id:3, country: "S", name: "NO", address: "I"}},
   {3: {id:4, country: "SXX", name: "NOI", address: "INDIA"}},
]

The solution i tried is returning null because of the nested objects structure i presume

var dataREsult =  data.filter(function(el) {
  return el.id == 4;
});

P.S: The structure of the data above is from the backend that iam working with.

I am a beginner with javascript. any help would be much appreciated.

John D
  • 285
  • 3
  • 22
  • 4
    Why is your data structured like that? – adiga Feb 05 '21 at 15:20
  • @adiga its the api response of a backend... – John D Feb 05 '21 at 15:22
  • As a data structure that makes little sense. It's needlessly nested, and each inner-object lives at an inconsistent key (first one 0, second 1 etc) so you'd have to use `Object.values()` to get at it. If at all possible, normalise the structure. – Mitya Feb 05 '21 at 15:22
  • @Mitya any example that you could show in terms of code? – John D Feb 05 '21 at 15:23
  • 1
    If it is possible to change the data, please change your server code. That is ridiculous. Of course you could do `return Object.values(el)[0].id === 4`. But, it will be hard to access and update the state with that structure. – adiga Feb 05 '21 at 15:23
  • Just a flat object, with IDs as keys, so `{1: {country: "SA", ...}, 2: {...}}` – Mitya Feb 05 '21 at 15:24
  • Are you saving this exact data in your state? You could use `data.flatMap(Object.values)` and use that array of objects without the additional nesting in your state. – adiga Feb 05 '21 at 15:27
  • If that really is your input data structure (it looks suspiciously like how some developer tools log plain arrays), then `const newFormat = data .flatMap (Object .values)` would yield a plain array of your values without the useless wrappers. And if you later had to return the manipulated data back to the server format, you could write `const oldFormat = newFormat .map ((x, i) => ({[i]: x}))`. This would make your internal work much simpler. – Scott Sauyet Feb 05 '21 at 15:58

1 Answers1

3

Use Object.values() inside Array.filter() callback.

const data = [
   {0: {id: 1, country: "SA", address: "IOXX"}},
   {1: {id:2, country: "SAP", name: "N", address: "IOP"}},
   {2: {id:3, country: "S", name: "NO", address: "I"}},
   {3: {id:4, country: "SXX", name: "NOI", address: "INDIA"}},
]

const result = data.filter(el => Object.values(el)[0].id === 4);

for(var i=data.length-1; i>=0; i--) {
  if(Object.values(data[i])[0].id === 4)
    data.splice(i, 1)
}


console.log(data);
wangdev87
  • 8,611
  • 3
  • 8
  • 31
  • thanks for the snippet, what would be the way to return only the `id` value, in case of you example `4`. I intend to create a function out of it. – John D Feb 05 '21 at 15:26
  • just same, you can make it as a function and return. – wangdev87 Feb 05 '21 at 15:27
  • @JohnD why would you want to return the `id` value if you are filtering by `id`? – adiga Feb 05 '21 at 15:32
  • @adiga i am trying to delete the item with `id = 4` in this example. I might be approaching it the wrong way but thats the ultimate goal. – John D Feb 05 '21 at 15:38
  • I updated my answer, you can use array.forEach, and use array.splice() to delete the item. @JohnD – wangdev87 Feb 05 '21 at 15:42
  • You can't `splice` inside `forEach`. It will work if there is only one entry that satisfies the condition. If there are 2 items with `id = 4`, it will splice the wrong item [Looping through array and removing items, without breaking for loop](https://stackoverflow.com/questions/9882284) – adiga Feb 05 '21 at 16:00
  • I got your point, i just updated, thanks @adiga – wangdev87 Feb 05 '21 at 16:02