Reputation: 1105
I have a structure like below;
var devices = {
'device-1' : {
'id' :'device1',
'template' :'template-1',
'user-1' :{
'name' : 'John Doe',
'authority' : 'author1',
},
'admin-1' :{
'name' : 'Bob Doe',
'authority' : 'author2',
},
'user-35' :{
'name' : 'Bill Doe',
'authority' : 'author1',
},
'author-42' :{
'name' : 'Jack Doe',
'authority' : 'author1|author3',
}
},
'device-2' : {
'id' :'device2',
'template' :'template-2',
'some-27' :{
'name' : 'John Doe',
'authority' : 'author1',
},
'other-42' :{
'name' : 'Jack Doe',
'authority' : 'author2',
}
},
'device-7' : {
'id' :'device7',
'template' :'template-1',
'user-2' :{
'name' : 'Samantha Doe',
'authority' : 'author2',
}
'admin-40' :{
'name' : 'Marry Doe',
'authority' : 'author1',
},
}
};
and I would like to get all 'value' entries of user-x elements by filtering their 'property' values.
Eg.
I would like filter all 'name's of users (no matter in which device and what are those user-ids) based on their 'authority' property and get 'John Doe','Bill Doe','Jack Doe','Marry Doe'
(as an array) if I would like filter for 'author1' 'authority' so I can get which users have 'author1' authorities on any devices.
I've checked many places (including StackOverflow) but most of the examples are limited to two-dimensional object arrays, variables were specific or objects were based on an integer (like [0] => Array).
But in this example, 'device-x'
and 'user-x'
entries are uncertain (so I cannot say their values are these) but 'name'
and 'authority'
keys are certain (assign by the system) and the count of these variables can be varied (crud operations).
Thanks right now.
UPDATE : Because of my assumption error (I thought that if I write user-x parts different that each other, people think that these values are not follow any rule) question was not clear. So I edited in code. Finally : owners of 'name' and 'authority' key-value pairs are user names and they are user defined.
So, all device objects will have id, template, unknown-user-field, but all unknown-user-fields must have 'name' and 'authority' key-value pairs.
Upvotes: 0
Views: 3805
Reputation: 35623
Using reduce
& filter
& map
.
Updated: I've added a isLikeUserObj
function that probs for name
& authority
fields.
const devices = {
'device-1': {
'id': 'device1',
'template': 'template-1',
'user-1': {
'name': 'John Doe',
'authority': 'author1',
},
'admin-1': {
'name': 'Bob Doe',
'authority': 'author2',
},
'user-35': {
'name': 'Bill Doe',
'authority': 'author1',
},
'author-42': {
'name': 'Jack Doe',
'authority': 'author1|author3',
}
},
'device-2': {
'id': 'device2',
'template': 'template-2',
'some-27': {
'name': 'John Doe',
'authority': 'author1',
},
'other-42': {
'name': 'Jack Doe',
'authority': 'author2',
}
},
'device-7': {
'id': 'device7',
'template': 'template-1',
'user-2': {
'name': 'Samantha Doe',
'authority': 'author2',
},
'admin-40': {
'name': 'Marry Doe',
'authority': 'author1',
},
}
};
const result = getUserByAuthority('author3');
function getUserByAuthority(requiredAuth) {
return Object.keys(devices).reduce((result, deviceKey) => {
const users = Object.keys(devices[deviceKey])
.filter((key) => isUserLikeObj(devices[deviceKey][key]))
.map(userKey => devices[deviceKey][userKey])
.filter((user) => user.authority.split('|').indexOf(requiredAuth) > -1)
.map((user) => user.name)
return result.concat(users);
}, [])
}
function isUserLikeObj(value) {
return typeof value === 'object' && value.hasOwnProperty('name') && value.hasOwnProperty('authority')
}
console.log(result)
Upvotes: 1
Reputation: 334
You can use for-in loop to traverse an object. Following ways could achieve your need
const result = []
for (let i in devices) {
for (let j in devices[i]) {
if (/user-\d+/.test(j)) {
if (devices[i][j].authority.split('|').indexOf('author1') !== -1) {
result.push(devices[i][j].name)
}
}
}
}
console.log(result)
Upvotes: 1