Reputation: 19
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
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
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
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
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
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