I have 3 people in the house ['John', 'Jane', 'Jack'],
We kept track of who opened/closed the door.
logs = [
{ name: "John", status: "opened" },
{ name: "Jane", status: "opened" },
{ name: "Jack", status: "opened" },
{ name: "Jane", status: "closed" },
{ name: "Jack", status: "closed" },
];
As you can see only 2 people ['Jane', 'Jack']
that opened and closed the door properly.
programmatically, I did these 3 steps to come to know that John is the person who opened and never closed the door.
let openers = logs.reduce((acc, log) => {
if (log.status === "opened") {
acc.push(log.name);
}
return acc;
}, []);
console.log(openers);
let closers = logs.reduce((acc, log) => {
if (log.status === "closed") {
acc.push(log.name);
}
return acc;
}, []);
console.log(closers);
let result = [];
closers.forEach((closer) => {
if (openers.includes(closer)) {
result.push(closer);
}
});
console.log(result);
I was trying to do these in one go in a single reduce()
, but I'm not too sure.
Can someone help me improve what I got
logs = [
{ name: "John", status: "opened" },
{ name: "Jane", status: "opened" },
{ name: "Jack", status: "opened" },
{ name: "Jane", status: "closed" },
{ name: "Jack", status: "closed" },
];
let openers = logs.reduce((acc, log) => {
if (log.status === "opened") {
acc.push(log.name);
}
return acc;
}, []);
console.log(openers);
let closers = logs.reduce((acc, log) => {
if (log.status === "closed") {
acc.push(log.name);
}
return acc;
}, []);
console.log(closers);
let result = [];
closers.forEach((closer) => {
if (openers.includes(closer)) {
result.push(closer);
}
});
console.log(result);
?
CodePudding user response:
You can do that with a single .reduce()
that keeps track of door status by name:
logs = [
{ name: "John", status: "opened" },
{ name: "Jane", status: "opened" },
{ name: "Jack", status: "opened" },
{ name: "Jane", status: "closed" },
{ name: "Jack", status: "closed" },
];
let statuses = logs.reduce((acc, log) => {
acc[log.name] = (log.status === 'opened');
return acc;
}, {});
console.log(statuses);
let culprits = Object.keys(statuses).filter(name => statuses[name]);
console.log(culprits);
Output:
{
"John": true,
"Jane": false,
"Jack": false
}
[
"John"
]
CodePudding user response:
It's bound to be a little more involved, because people can open and close the door multiple times.
This approach finds the people for which the number of openings/closings don't match.
const logs = [
{ name: "John", status: "opened" },
{ name: "Jane", status: "opened" },
{ name: "Jack", status: "opened" },
{ name: "Jane", status: "closed" },
{ name: "Jack", status: "closed" },
];
const result = Object.entries(logs.reduce((a, v) => {
a[v.name] = a[v.name] || 0;
a[v.name] = v.status === 'opened' ? 1 : -1;
return a;
}, {})).filter(([_, v]) => v).map(([k]) => k);
console.log(result);