Reputation: 274
I want to simplify an array of objects filtering. Let's assume that I have following array,
const users = [{
name: "user1",
gender: "m"
}, {
name: "user2",
gender: "f"
}, {
name: "user3",
gender: "f"
}, {
name: "user4",
gender: "m"
}, {
name: "user5",
gender: "m"
}];
For example i need to filter all users by male or female, so i do loop through filter object property:
const fUsers = users.filter(user => user.gender === "f");
const mUsers = users.filter(user => user.gender === "m");
const results = [fUsers, mUsers];
console.log(results);
Is there any better way to filter to do it in one shot, so i can get results in mutiple arrays.
Upvotes: 2
Views: 141
Reputation: 1083
this will work, instead of two filters, you can reduce into an array of two arrays, sorting as you go. the acc is set after the function that reduce uses.
const sortedByGender =users.reduce((acc, user)=>{
user.gender==="f"?acc[0].push(user):acc[1].push(user);
return acc;
},[[],[]]);
Upvotes: 0
Reputation: 3053
Basically for any kind of operation with array, you can use a forEach
.In this case you just create as much help variables as you neeed and process filter logic in forEach
.
const males = []
const females = []
users.forEach(u=> u.gender === 'm' ? males.push(u) : females.push(u))
Another simple solution is to use one of javascript loops, in my example I have chosen for-in
but principle is the same as in forEach
example
const males = []
const females = []
for (u in users) {
if (u.gender === 'm') {
males.push(u)
} else {
females.push(u)
}
}
Reduce is function which allows as to process array loop and store result to single variable called accumulator, which is shared in every loop step. We can use [[],[]]
=> array of arrays accumulator
const [males, females] = users.reduce((acc, user) => {
if (user.gender === 'm') {
acc[0].push(u)
} else {
acc[1].push(u)
}
return acc;
}, [[], []])
Same principle as the last, but refactored to one line. (not the beast readability)
const [males, females] = users.reduce((acc, u) => (u.gender === 'm' ? acc[0].push(u) : acc[1].push(u), acc), [[],[]])
If you use lodash, you can use a groupBy function, which create object with keys consist of filter attributes and array values, same function you can find also in underscore.
const result = _.groupBy(users, 'gender'));
// { 'm': [{male1, male2}], 'f': [female1, female2] }
Upvotes: 2
Reputation: 386550
You could group by gender and take a destructuring with a renaming to the wanted variable names.
const
users = [{ name: "user1", gender: "m" }, { name: "user2", gender: "f" }, { name: "user3", gender: "f" }, { name: "user4", gender: "m" }, { name: "user5", gender: "m" }],
{ f: fUsers, m: mUsers } = users.reduce((r, o) => ((r[o.gender] ??= []).push(o), r), {});
console.log(fUsers);
console.log(mUsers);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 10193
This can be done using Array.reduce
.
On Array.reduce
callback, if gender is m
, you can push
to acc[0]
and if gender
is f
, you can push
to acc[1]
.
const users = [{
name: "user1",
gender: "m"
}, {
name: "user2",
gender: "f"
}, {
name: "user3",
gender: "f"
}, {
name: "user4",
gender: "m"
}, {
name: "user5",
gender: "m"
}];
const result = users.reduce((acc, cur) => {
cur.gender === 'f' ? acc[0].push(cur) : acc[1].push(cur);
return acc;
}, [ [], [] ]);
console.log(result);
Upvotes: 3
Reputation: 50291
You can use reduce function and in the accumulator pass a nested array. In the callback check the gender and you can use acc[0]
to add elements in the first nested array of the accumulator or acc[1]
const users = [{
name: "user1",
gender: "m"
}, {
name: "user2",
gender: "f"
}, {
name: "user3",
gender: "f"
}, {
name: "user4",
gender: "m"
}, {
name: "user5",
gender: "m"
}];
const newArr = users.reduce((acc, curr) => {
if (curr.gender === 'f') {
acc[0].push(curr)
} else {
acc[1].push(curr)
}
return acc;
}, [
[],
[]
]);
console.log(newArr)
Alternatively you can also use normal for loop
const users = [{
name: "user1",
gender: "m"
}, {
name: "user2",
gender: "f"
}, {
name: "user3",
gender: "f"
}, {
name: "user4",
gender: "m"
}, {
name: "user5",
gender: "m"
}];
let arr = [
[],
[]
];
for (let i = 0; i < users.length; i++) {
users[i].gender === 'f' ? arr[0].push(users[i]) : arr[1].push(users[i])
};
console.log(arr)
Upvotes: 4