Home > Enterprise >  How can construct a new array based on multiple property values?
How can construct a new array based on multiple property values?

Time:12-09

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);

  • Related