Reputation: 1334
Given the object array:
var teachers = [
{
FullName: "Mark Jones",
Address: "123 Main Street",
Students: {
Monday: {
Stone: ["8:30", "10:30"],
Cameron: [" ", " "],
Julia: [" ", " "],
Zoe: ["3:30", "5:30"]
},
Tuesday: {
Jordan: ["12:00", "1:00"],
Hal: [" ", " "],
Kiko: [" ", " "]
}
}
},
{
FullName: "Skip Roberts",
Address: "123 Main Street",
Students: {
Monday: {
Hal: ["9:30", "10:30"],
Hana: [" ", " "],
Ron: [" ", " "],
Lola: ["4:30", "5:30"]
},
Tuesday: {
Josh: ["11:00", "12:00"],
George: [" ", " "],
Paula: ["5:00", "6:00"]
}
}
}
]
I'm wanting to retrieve all the keys (the student names) for all values equal to [" ", " "]. I tried the following but it only gives the first key and skips the rest (here I'm getting the keys for Monday:
var array = [];
teachers.forEach(function (doc) {
array.push(_.findKey(doc.Students.Monday, [" ", " "]));
});
console.log(array);
This outputs:
["Cameron", "Hana"]
I'm wanting:
["Cameron", "Julia", "Hana", "Ron"]
Upvotes: 0
Views: 69
Reputation: 27976
Here's a solution using underscore:
var result = _.chain(teachers)
.pluck('Students')
.map(day => _.pick(day.Monday, times => times[0] == ' ' && times[1] == ' '))
.flatten()
.map(_.keys)
.flatten()
.value()
Upvotes: 2
Reputation: 22474
The problem is that _.findKey
retrieves only the first key and there doesn't seem to be any function for retrieve all of them.
If you're not looking for an underscore solution you can do this in vanilla JavaScript using a function like this one:
var arr = [];
function lookForEmpty(obj){
for(var k in obj){
var v = obj[k];
if(v instanceof Array){
if(v.length == 2 && v[0] == " " && v[1] == " "){
arr.push(k);
}
}else if(v instanceof Object){
lookForEmpty(v);
}
}
}
lookForEmpty(teachers);
Upvotes: 1
Reputation: 350167
Here are two native JavaScript (ES6) functions, one for a given day, and one for any day. They also make sure a name is listed only once:
function getStudentsForDay(teachers, day) {
return [...teachers.reduce( (col, teacher) =>
Object.keys(teacher.Students[day]).reduce(
(col, name) => teacher.Students[day][name].every(time => time == ' ')
? col.add(name) : col,
col
), new Set()
)];
}
function getStudentsForAnyDay(teachers) {
return [...teachers.reduce( (col, teacher) =>
Object.keys(teacher.Students).reduce( (col, day) =>
Object.keys(teacher.Students[day]).reduce(
(col, name) => teacher.Students[day][name].every(time => time == ' ')
? col.add(name) : col,
col
), col
), new Set()
)];
}
var teachers = [
{
FullName: "Mark Jones",
Address: "123 Main Street",
Students: {
Monday: {
Stone: ["8:30", "10:30"],
Cameron: [" ", " "],
Julia: [" ", " "],
Zoe: ["3:30", "5:30"]
},
Tuesday: {
Jordan: ["12:00", "1:00"],
Hal: [" ", " "],
Kiko: [" ", " "]
}
}
},
{
FullName: "Skip Roberts",
Address: "123 Main Street",
Students: {
Monday: {
Hal: ["9:30", "10:30"],
Hana: [" ", " "],
Ron: [" ", " "],
Lola: ["4:30", "5:30"]
},
Tuesday: {
Josh: ["11:00", "12:00"],
George: [" ", " "],
Paula: ["5:00", "6:00"]
}
}
}
];
console.log('For Monday: ', getStudentsForDay(teachers, 'Monday'));
console.log('For any day: ', getStudentsForAnyDay(teachers));
Upvotes: 1
Reputation: 6110
Below is one possible way in vanilla JS, using the .reduce()
and .filter()
methods. You could use their underscore counterparts just as well.
var teachers = [{
FullName: "Mark Jones",
Address: "123 Main Street",
Students: {
Monday : { Stone: ["8:30", "10:30"], Cameron: [" ", " "], Julia: [" ", " "], Zoe: ["3:30", "5:30"] },
Tuesday: { Jordan: ["12:00", "1:00"], Hal: [" ", " "], Kiko: [" ", " "] }
}
}, {
FullName: "Skip Roberts",
Address: "123 Main Street",
Students: {
Monday : { Hal: ["9:30", "10:30"], Hana: [" ", " "], Ron: [" ", " "], Lola: ["4:30", "5:30"] },
Tuesday: { Josh: ["11:00", "12:00"], George: [" ", " "], Paula: ["5:00", "6:00"] }
}
}];
function findStudents(day) {
return teachers.reduce(function(res, cur) {
var student = cur.Students[day];
return res.concat(Object.keys(student).filter(function(k) {
return (student[k][0] == " " && student[k][1] == " ");
}));
}, []);
}
var res = findStudents("Monday");
console.log(res);
Upvotes: 1