admin管理员组文章数量:1287583
Trying to filter an array of objects by eliminating objects that have a specific property that exists already in another object (duplicate). The decision which object to remove should be based on another property.
Example: For an array of objects, that might look like this, the goal would be to filter all "user" duplicates and keep the one with the oldest "date" property.
const arr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
{user: 'Alex', date: '1840801929948'},
]
Expected oute:
filteredArr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
]
I managed the basic filtering that works for keeping only unique objects.
const filteredArr = arr.reduce((unique, o) => {
if(!unique.some(obj => obj.user === o.user) {
unique.push(o);
}
return unique;
},[]);
Though I can't figure out, what to do so that in the case of a duplicate the "oldest" object stays and the latest get removed. Thanks so much for your help! Really appreciated.
Trying to filter an array of objects by eliminating objects that have a specific property that exists already in another object (duplicate). The decision which object to remove should be based on another property.
Example: For an array of objects, that might look like this, the goal would be to filter all "user" duplicates and keep the one with the oldest "date" property.
const arr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
{user: 'Alex', date: '1840801929948'},
]
Expected oute:
filteredArr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
]
I managed the basic filtering that works for keeping only unique objects.
const filteredArr = arr.reduce((unique, o) => {
if(!unique.some(obj => obj.user === o.user) {
unique.push(o);
}
return unique;
},[]);
Though I can't figure out, what to do so that in the case of a duplicate the "oldest" object stays and the latest get removed. Thanks so much for your help! Really appreciated.
Share Improve this question edited Oct 29, 2018 at 9:27 YvonC asked Oct 29, 2018 at 9:22 YvonCYvonC 3492 gold badges6 silver badges23 bronze badges 4-
is your data sorted by
date
? – Nina Scholz Commented Oct 29, 2018 at 9:25 - No unfortunately not. The objects are in real usecase much bigger and sorted in different ways depending on where used... – YvonC Commented Oct 29, 2018 at 9:29
- do you habe only the given two properties or more? do you want to keep the objects? – Nina Scholz Commented Oct 29, 2018 at 9:34
- Yes, there are more properties. Don't plan to keep the objects. – YvonC Commented Oct 29, 2018 at 9:44
4 Answers
Reset to default 7Reduce the array to an object with the user
as the key. If a user is not in unique
object, or if it's date is "older" than the what that is, add it to the object. Convert the object to array with Object.values()
.
Note: since you the dates are string, convert them to a number while paring (I use the +
operator).
const array = [{ user: 'Alex', date: '1540801929945' }, { user: 'Bill', date: '1640801929946' }, { user: 'Carl', date: '1740801929947' }, { user: 'Alex', date: '1840801929948' }];
const filteredArray = Object.values(array.reduce((unique, o) => {
if(!unique[o.user] || +o.date > +unique[o.user].date) unique[o.user] = o;
return unique;
}, {}));
console.log(filteredArray);
A solution with Map
and a single loop approach
var array = [{ user: 'Alex', date: '1540801929945' }, { user: 'Bill', date: '1640801929946' }, { user: 'Carl', date: '1740801929947' }, { user: 'Alex', date: '1840801929948' }],
filtered = Array.from(array
.reduce((m, o) => !m.has(o.user) || m.get(o.user).data > o.date
? m.set(o.user, o)
: m, new Map)
.values());
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For sorted data (take sorting in advance by date
), you could use a Set
for filtering.
var array = [{ user: 'Alex', date: '1540801929945' }, { user: 'Bill', date: '1640801929946' }, { user: 'Carl', date: '1740801929947' }, { user: 'Alex', date: '1840801929948' }],
filtered = array
.sort(({ date: a }, { date: b }) => a - b)
.filter((s => ({ user }) => !s.has(user) && s.add(user))(new Set));
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For an O(N)
solution, reduce
into an object indexed by user
, whose values are date
s - on each iteration, if something at that user
already exists, keep only the lowest date
. Then, iterate over the object's entries
to turn it back into an array:
const arr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
{user: 'Alex', date: '1840801929948'},
{user: 'Carl', date: '1340801929947'},
];
const arrByUser = arr.reduce((a, { user, date }) => {
if (!a[user]) a[user] = date;
else if (a[user].localeCompare(date) === 1) a[user] = date;
return a;
}, {});
const output = Object.entries(arrByUser)
.map(([user, date]) => ({ user, date }));
console.log(output);
I believe you actually need to know the index of the non-unique element (Object with name "Alex" in your case) and then pare their dates, saving the older one.
Array.prototype.find wil lnot do you mouch good in this case. However, Array.prototype.find can be of help since it takes a callback which returns a boolean( just like 'some') BUT it returns the index of the element matched by your callback, or undefined if no such element is found.
Give it a try, it cant hurt :)
本文标签:
版权声明:本文标题:javascript - JS - Filter an array of objects for duplicates of one property, and decide which object to keep based on another pr 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741307948a2371480.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论