Reputation: 193
This question has been proposed many times in SO, but they all refer to an array of objects.
In my case, I would like to filter an object of objects.
Say I have this object:
"Users": {
"w14FKo72BieZwbxwUouTpN7UQm02": {
"name": "Naseebullah Ahmadi",
"userType": "Patient",
"writePermission": false
},
"SXMrXfBvexQUXfnVg5WWVwsKjpD2": {
"name": "Levi Yeager",
"userType": "Patient",
"writePermission": false
},
"VoxHFgUEIwRFWg7JTKNXSSoFoMV2": {
"name": "Ernest Kamavuako",
"userType": "Doctor",
"writePermission": true
},
"hFoWuyxv6Vbt8sEKA87T0720tXV2": {
"name": "Karla Stanlee",
"userType": "Doctor",
"writePermission": true
}
}
I would like to filter this so I can get the following:
"UsersCustom": {
"w14FKo72BieZwbxwUouTpN7UQm02": {
"name": "Naseebullah Ahmadi",
"userType": "Patient",
"writePermission": false
},
"SXMrXfBvexQUXfnVg5WWVwsKjpD2": {
"name": "Levi Yeager",
"userType": "Patient",
"writePermission": false
}
}
Note that this object "User" is huge in reality (over 1000 entries) and each user has more attributes than mere "name", "userType", and "writePermission".
The reason why I need to filter the user's object is so that I can get users who are only (Patient) and get the id of that Patient to lookup in another object and finally merge them all in one object.
// user is the object as seen above
let Patients = users ? (
// I loop through them
Object.keys(users).map((uid, i) => {
// get individual patient
const patient = users[uid];
// check their userType
if (patient.userType === "Patient") {
let customPatient = {
uid: uid,
name: patient.name,
profession: patient.profession,
history: null,
ecg: null,
heartSound: null
};
this._healthRef(uid).then(health => {
customPatient.history = health;
return this._heartSoundRef(uid).then(HS => HS);
}).then(HS => {
customPatient.heartSound = HS;
return this._ecgRef(uid).then(a => a);
}).then(ecg => {
customPatient.ecg = ecg;
}).then(() => {
cusomPatients.push(customPatient);
})
}
})
)
My solution above is, although partially complete, is still not efficient and wrong. Because I need the Id of each patient for other lookup
Currently, most solution provides looping through the entries, which means that it will run O(n) in worst case. Is there any possibility that it can be solved quicker than O(n)?
Upvotes: 2
Views: 3808
Reputation: 22876
My guess is that filtering during parsing might be most efficient (haven't measured/compaed it):
j = '{"w14FKo72BieZwbxwUouTpN7UQm02":{"name":"Naseebullah Ahmadi","userType":"Patient","writePermission":false},"SXMrXfBvexQUXfnVg5WWVwsKjpD2":{"name":"Levi Yeager","userType":"Patient","writePermission":false},"VoxHFgUEIwRFWg7JTKNXSSoFoMV2":{"name":"Ernest Kamavuako","userType":"Doctor","writePermission":true},"hFoWuyxv6Vbt8sEKA87T0720tXV2":{"name":"Karla Stanlee","userType":"Doctor","writePermission":true}}'
o = JSON.parse(j, (k, v) => !v.userType || v.userType === 'Patient' ? v : void 0)
console.log(o)
Caching the filtered object would be even more efficient to reduce network traffic.
Upvotes: 1
Reputation: 2970
Using reduce
method you can get your object
var data = {
"w14FKo72BieZwbxwUouTpN7UQm02": {
"name": "Naseebullah Ahmadi",
"userType": "Patient",
"writePermission": false
},
"SXMrXfBvexQUXfnVg5WWVwsKjpD2": {
"name": "Levi Yeager",
"userType": "Patient",
"writePermission": false
},
"VoxHFgUEIwRFWg7JTKNXSSoFoMV2": {
"name": "Ernest Kamavuako",
"userType": "Doctor",
"writePermission": true
},
"hFoWuyxv6Vbt8sEKA87T0720tXV2": {
"name": "Karla Stanlee",
"userType": "Doctor",
"writePermission": true
}
};
var results = Object.keys(data).reduce(function(acc, val) {
if(data[val].userType === 'Patient') acc[val] = data[val];
return acc;
}, {});
console.log(results);
Upvotes: 5
Reputation: 36703
Use for...in
to iterate through object and check if ther usertype is patient or not.
var users = {
"Users": {
"w14FKo72BieZwbxwUouTpN7UQm02": {
"name": "Naseebullah Ahmadi",
"userType": "Patient",
"writePermission": false
},
"SXMrXfBvexQUXfnVg5WWVwsKjpD2": {
"name": "Levi Yeager",
"userType": "Patient",
"writePermission": false
},
"VoxHFgUEIwRFWg7JTKNXSSoFoMV2": {
"name": "Ernest Kamavuako",
"userType": "Doctor",
"writePermission": true
},
"hFoWuyxv6Vbt8sEKA87T0720tXV2": {
"name": "Karla Stanlee",
"userType": "Doctor",
"writePermission": true
}
}
};
for(let user in users.Users){
if(users.Users.hasOwnProperty(user) && users.Users[user].userType!=="Patient")
delete users.Users[user];
}
console.log(users);
This will modify the object, if you want to preserve it then just do a deep copy of the original object.
Upvotes: 0
Reputation: 122087
You can use reduce()
method on your object keys and build new object from that.
const obj = {"Users":{"w14FKo72BieZwbxwUouTpN7UQm02":{"name":"Naseebullah Ahmadi","userType":"Patient","writePermission":false},"SXMrXfBvexQUXfnVg5WWVwsKjpD2":{"name":"Levi Yeager","userType":"Patient","writePermission":false},"VoxHFgUEIwRFWg7JTKNXSSoFoMV2":{"name":"Ernest Kamavuako","userType":"Doctor","writePermission":true},"hFoWuyxv6Vbt8sEKA87T0720tXV2":{"name":"Karla Stanlee","userType":"Doctor","writePermission":true}}}
const newObj = {
'UserCustom': Object.keys(obj.Users).reduce((r, k) => {
if(obj.Users[k].userType == 'Patient') r[k] = Object.assign({}, obj.Users[k])
return r;
}, {})
}
console.log(newObj)
Upvotes: 0
Reputation: 1075199
You can solve this with for-in
or Object.keys
or (on modern JavaScript engines) Object.entries
.
for-in
provides a means of iterating through the object's enumerable properties; you can then use those property names to look up the value:
var result = {};
for (var key in users) {
var entry = users[key];
if (entry.userType === "Patient") {
result[key] = entry;
}
}
Live Example:
var users = {
"w14FKo72BieZwbxwUouTpN7UQm02": {
"name": "Naseebullah Ahmadi",
"userType": "Patient",
"writePermission": false
},
"SXMrXfBvexQUXfnVg5WWVwsKjpD2": {
"name": "Levi Yeager",
"userType": "Patient",
"writePermission": false
},
"VoxHFgUEIwRFWg7JTKNXSSoFoMV2": {
"name": "Ernest Kamavuako",
"userType": "Doctor",
"writePermission": true
},
"hFoWuyxv6Vbt8sEKA87T0720tXV2": {
"name": "Karla Stanlee",
"userType": "Doctor",
"writePermission": true
}
};
var result = {};
for (var key in users) {
var entry = users[key];
if (entry.userType === "Patient") {
result[key] = entry;
}
}
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}
Object.keys
gives you an array of the object's own enumerable properties, so:
var result = {};
Object.keys(users).forEach(function(key) {
var entry = users[key];
if (entry.userType === "Patient") {
result[key] = entry;
}
});
Live Example:
var users = {
"w14FKo72BieZwbxwUouTpN7UQm02": {
"name": "Naseebullah Ahmadi",
"userType": "Patient",
"writePermission": false
},
"SXMrXfBvexQUXfnVg5WWVwsKjpD2": {
"name": "Levi Yeager",
"userType": "Patient",
"writePermission": false
},
"VoxHFgUEIwRFWg7JTKNXSSoFoMV2": {
"name": "Ernest Kamavuako",
"userType": "Doctor",
"writePermission": true
},
"hFoWuyxv6Vbt8sEKA87T0720tXV2": {
"name": "Karla Stanlee",
"userType": "Doctor",
"writePermission": true
}
};
var result = {};
Object.keys(users).forEach(function(key) {
var entry = users[key];
if (entry.userType === "Patient") {
result[key] = entry;
}
});
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}
Object.entries
provides an iterable which consists of the name and value of each own, enumerable property. It's quite new. So for instance (in ES2015+ syntax where Object.entries
was added in ES2017 but can be polyfilled):
const result = {};
for (const [key, value] of Object.entries(users)) {
if (value.userType === "Patient") {
result[key] = value;
}
}
Live Example:
const users = {
"w14FKo72BieZwbxwUouTpN7UQm02": {
"name": "Naseebullah Ahmadi",
"userType": "Patient",
"writePermission": false
},
"SXMrXfBvexQUXfnVg5WWVwsKjpD2": {
"name": "Levi Yeager",
"userType": "Patient",
"writePermission": false
},
"VoxHFgUEIwRFWg7JTKNXSSoFoMV2": {
"name": "Ernest Kamavuako",
"userType": "Doctor",
"writePermission": true
},
"hFoWuyxv6Vbt8sEKA87T0720tXV2": {
"name": "Karla Stanlee",
"userType": "Doctor",
"writePermission": true
}
};
const result = {};
for (const [key, value] of Object.entries(users)) {
if (value.userType === "Patient") {
result[key] = value;
}
}
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}
Upvotes: 0