Reputation: 553
I have two arrays like this:
owners: [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "[email protected]"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "[email protected]"
}
]
users: [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "[email protected]"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "[email protected]"
},
{
userID: "88c4d7ac",
username: "User3.Name3",
firstName: "User3",
lastName: "Name3",
email: "[email protected]"
}
]
I would like to get an array of users which contains only the elements which are not in the owners array.
I tried different approaches. Finally, I ended up with the solution:
const usersItems = users.map(user => {
// Check whether the user is already an owner
if (owners.findIndex(owner => owner.userID === user.userID) === -1) {
return owner
} else {
return null;
}
});
console.log(usersItems);
// Filter out all items which are null
const newUsersItems = usersItems.filter(user => {
if (user) return user;
});
console.log(usersItems);
To me, it doesn't' look like a clean solution. Is there a cleaner and easier way to do this? As a result, I would like to have:
newUsers: [
{
userID: "88c4d7ac",
username: "User3.Name3",
firstName: "User3",
lastName: "Name3",
email: "[email protected]"
}
]
Upvotes: 1
Views: 84
Reputation: 17190
First you can create a Set() with the userID's
of the owners
array, and then you can use Array.filter() on the users
array to filter the users whose userID
does not belong to the previous created set.
const owners = [
{userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "[email protected]"},
{userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "[email protected]"}
];
const users = [
{userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "[email protected]"},
{userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "[email protected]"},
{userID: "88c4d7ac", username: "User3.Name3", firstName: "User3", lastName: "Name3", email: "[email protected]"}
];
let ownerIdsSet = new Set(owners.map(x => x.userID));
let res = users.filter(x => !ownerIdsSet.has(x.userID));
console.log(res);
.as-console {background-color:black !important; color:lime;}
But why to construct a Set first?
In summary, it will improve the performance of the filtering process, particularly if the owners
array is large. You should note that methods like findIndex()
, find()
and some()
needs to traverse the array for check to the related condition while checking if the userID
belongs to the Set
is a O(1)
calculation. However, of course, there will be an extra overload at initialization to create the mentioned Set.
Upvotes: 2
Reputation: 33726
You can use the function some
or find
, this approach uses the function find
let owners = [ { userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "[email protected]" }, { userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "[email protected]" } ],
users = [ { userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "[email protected]" }, { userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "[email protected]" }, { userID: "88c4d7ac", username: "User3.Name3", firstName: "User3", lastName: "Name3", email: "[email protected]" } ],
result = users.filter(({userID}) => !owners.find(o => o.userID === userID));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 1631
You can use combination of filter and some functions like this:
const owners = [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "[email protected]"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "[email protected]"
}
];
const users = [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "[email protected]"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "[email protected]"
},
{
userID: "88c4d7ac",
username: "User3.Name3",
firstName: "User3",
lastName: "Name3",
email: "[email protected]"
}
];
const result = users.filter(user => !owners.some(owner => owner.userID === user.userID));
console.log(result);
Upvotes: 2
Reputation: 1570
You can use the reduce function
const diff = users.reduce((acc, user) => {
if(!owners.find(owner => owner.id === user.id){
acc.push(user);
}
return acc;
}, []);
to avoid use the find() function every loop you can store owner ids in a array with the map an just use includes()
const ownersIds = owners.map(owner => owner.id);
const diff = users.reduce((acc, user) => {
if(!ownersIds.includes(user.id){
acc.push(user);
}
return acc;
}, []);
Upvotes: 0
Reputation: 985
You could get rid of your map
and just use the filter, (that's exactly what filter is for) somthing like
const filtered = users.filter(user => {
// Check whether the user is already an owner
return owners.findIndex(owner => owner.userID === user.userID) === -1
});
would probably work
Upvotes: 5
Reputation: 11126
You can just use a single .filter()
function, like so:
let owners = [{userID: "58c4d7ac",username: "John.Doe",firstName: "John",lastName: "Doe",email: "[email protected]"},{userID: "68c4d7ac",username: "User2.Name2",firstName: "User2",lastName: "Name2",email: "[email protected]"}];
let users = [{userID: "58c4d7ac",username: "John.Doe",firstName: "John",lastName: "Doe",email: "[email protected]"},{userID: "68c4d7ac",username: "User2.Name2",firstName: "User2",lastName: "Name2",email: "[email protected]"},{userID: "88c4d7ac",username: "User3.Name3",firstName: "User3",lastName: "Name3",email: "[email protected]"}];
let newUsersItems = users.filter(user => owners.findIndex(owner => owner.userID === user.userID) === -1);
console.log(newUsersItems)
You can just use a single .filter()
function, like so:
Upvotes: 1
Reputation: 37755
You can use filter and some
const owners = [{userID:"58c4d7ac",username:"John.Doe",firstName:"John",lastName:"Doe",email:"[email protected]"},{userID:"68c4d7ac",username:"User2.Name2",firstName:"User2",lastName:"Name2",email:"[email protected]"}]
const users = [{userID:"58c4d7ac",username:"John.Doe",firstName:"John",lastName:"Doe",email:"[email protected]"},{userID:"68c4d7ac",username:"User2.Name2",firstName:"User2",lastName:"Name2",email:"[email protected]"},{userID:"88c4d7ac",username:"User3.Name3",firstName:"User3",lastName:"Name3",email:"[email protected]"}]
const newUsers = users
.filter(({userID}) => !owners.some(({userID:ownerID})=> ownerID === userID))
console.log(newUsers)
Upvotes: 1