Reputation: 2248
I want to be able to return duplicates except first occurance in an array of objects based of the place and keyword. Both should match and return the documents in an new array. Here is my trial run:
var things = [
{place: 'hello', keyword: 'hey', id: 0},
{place: 'hi', id: 1},
{place: 'hello', keyword: 'hey', id: 2},
{place: 'hello', keyword: 'man', id: 3}
]
var duplicates = [];
things.forEach((item, index) => {
if(things.indexOf(item.place) != index && things.indexOf(item.keyword) != index) {
duplicates.push(item);
}
});
Expected output:
[{place: 'hello', keyword: 'hey', id: 2}]
Any help would be great (without any frameworks, just ES6 or older). Thanks
EDIT: It should match multiple specified values such as keyword and place.
Upvotes: 1
Views: 454
Reputation: 386654
You could count the same keys and filter if the count is greater than one with an object for counting
const
getKey = o => keys.map(k => o[k]).join('|'),
keys = ['place', 'keyword'],
things = [{ place: 'hello', keyword: 'hey', id: 0 }, { place: 'hi', id: 1 }, { place: 'hello', keyword: 'hey', id: 2 }, { place: 'hello', keyword: 'man', id: 3 }],
hash = Object.create(null),
duplicates = things.filter(o =>
(k => (hash[k] = (hash[k] || 0) + 1) > 1)
(getKey(o))
);
console.log(duplicates);
Upvotes: 2
Reputation: 35222
You could group the items based on place
and then get the first item from those groups with length > 1
const things = [{ place: 'hello', keyword: 'hey', id: 0 }, { place: 'hi', id: 1 }, { place: 'hello', keyword: 'hey', id: 2 }, { place: 'hello', keyword: 'man', id: 3 }];
const merged = things.reduce((r, a) => {
(r[a.place] = r[a.place] || []).push(a)
return r
}, {})
const final = Object.values(merged)
.filter(a => a.length > 1)
.map(a => a[1])
console.log(final)
Upvotes: 0
Reputation: 6582
The obvious solution is that you'll have to track the objects you have seen in order to do it how you want.
const seen = [];
const duplicates = [];
things.forEach(item => {
const sawItem = seen.find(seenItem => item.place === seenItem.place && item.keyword === seenItem.keyword)
if (sawItem) {
duplicates.push(sawItem);
} else {
seen.push(sawItem);
}
});
This isn't a very efficient algorithm however, so I'm curious to see a better way to do it.
Upvotes: 0