skywalker
skywalker

Reputation: 19

How to find all values of a specific key in an array of nested objects?

How would I find all values of a specific key in an array of nested objects?

Example data:

[
  {
    "id": 14252373,
    "name": "foo",
    "url": "/test",
    "private": true,
    "owner": {
        "login": "username",
        "id": 1217786,
    },
    "permissions": {
        "admin": {
            "id": 1567283
        },
        "push": false,
        "pull": true
        }
  }
]

How would I get an array of all id values?

Desired output: [14252373, 1217786, 1567283]

Upvotes: 1

Views: 846

Answers (5)

vincent
vincent

Reputation: 2181

We use object-scan for many data processing tasks. Once you wrap your head around how to use it, it is quite handy. Here is how you could answer your question

// const objectScan = require('object-scan');

const find = (input) => objectScan(['**.id'], { rtn: 'value' })(input);

const arr = [{ id: 14252373, name: 'foo', url: '/test', private: true, owner: { login: 'username', id: 1217786 }, permissions: { admin: { id: 1567283 }, push: false, pull: true } }];

console.log(find(arr));
// => [ 1567283, 1217786, 14252373 ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

Upvotes: 1

George Kafkias
George Kafkias

Reputation: 16

Since it's an array of objects, I think a simple forEach would help make this really easy:

let data = [{
  id: 14252373,
  name: "foo",
  url: "/test",
  private: true,
  owner: {
    login: "username",
    id: 1217786
  },
  permissions: {
    admin: {
      id: 1567283
    },
    push: false,
    pull: true
  },
},
{
  id: 222222222,
  name: "foo",
  url: "/test",
  private: true,
  owner: {
    login: "username",
    id: 1217786
  },
  permissions: {
    admin: {
      id: 1567283
    },
    push: false,
    pull: true
  },
},

];

let everyID = [];

data.forEach(item => {
  everyID.push(item.id);
});

console.log(everyID);

Upvotes: 0

brk
brk

Reputation: 50291

You can use reduce and a recursive function. Inside the reduce callback check if the current item under iteration is an object or not, If so then call the recursive function

let data = [{
  id: 14252373,
  name: "foo",
  url: "/test",
  private: true,
  owner: {
    login: "username",
    id: 1217786
  },
  permissions: {
    admin: {
      id: 1567283
    },
    push: false,
    pull: true
  }
}];

let ids = data.reduce((acc, curr) => {
  for (let keys in curr) {
    if (keys === "id") {
      acc.push(curr[keys]);
    } else if (typeof curr[keys] === "object" && curr[keys] !== null) {
      acc = recurObj(curr[keys], acc);
    }
  }
  return acc;
}, []);

function recurObj(val, arr) {
  for (let keys in val) {
    if (keys === "id") {
      arr.push(val[keys]);
    } else if (typeof val[keys] === "object" && val[keys] !== null) {
      recurObj(val[keys], arr);
    }
  }
  return arr;
}
console.log(ids);

Upvotes: 0

Lonnie Best
Lonnie Best

Reputation: 11364

There are multiple ways to accomplish this. One interesting way is to convert the structure to JSON and extract the IDs using a regular expression:

let ary = 
[
  {
    "id": 14252373,
    "name": "foo",
    "url": "/test",
    "private": true,
    "owner": {
        "login": "username",
        "id": 1217786,
    },
    "permissions": {
        "admin": {
            "id": 1567283
        },
        "push": false,
        "pull": true
        }
  }
];

let json = JSON.stringify(ary);
let idMatcher = /(?<="id":\s*)\d+/gmu;
let ids = json.match(idMatcher);

console.log(ids);

Upvotes: 1

adiga
adiga

Reputation: 35222

You could create a function and loop through the keys in the passed object. If the current key is same as the key to find, add the value to the output. If the current key is an object, recursively call the function on the current value

function getValue(o, findKey) {
  const output = []
  
  for (const k in o) {
    if (k === findKey)
      output.push(o[k])
    else if (typeof o[k] === 'object')
      output.push(...getValue(o[k], findKey))
  }
  
  return output;
}

getValue(input, 'id')

Here's a snippet:

const input = [{
  "id": 14252373,
  "name": "foo",
  "url": "/test",
  "private": true,
  "owner": {
    "login": "username",
    "id": 1217786,
  },
  "permissions": {
    "admin": {
      "id": 1567283
    },
    "push": false,
    "pull": true
  }
}]

function getValue(o, findKey) {
  const output = []
  
  for (const k in o) {
    if (k === findKey)
      output.push(o[findKey])
    else if (typeof o[k] === 'object')
      output.push(...getValue(o[k], findKey))
  }
  
  return output;
}

console.log(getValue(input, 'id'))

Upvotes: 1

Related Questions