I was originally iterating through my array to remove any duplicates and only to return the unique values. However, I was wondering if it was possible to identify the duplicates and update their label in the original array in order to keep some of the original data that they contain. As of now, I been removing duplicates by doing the following:
const removeDuplicates = arrayCollection
.filter((link, i) => i === arrayCollection.findIndex((l) => (
l.collectionTitle === link.collectionTitle
)));
What I would like to do is for the collection title to attach something like "Link (0), Link (1)" if they share the same title. Overall, I'm trying to find a way to not remove the duplicates after finding them but rather to append something to differentiate them in the original array collection.
a sample of arrayCollection:
[
{id: '1', collectionTitle: '456'},
{id: '2', collectionTitle: '123'},
{id: '3', collectionTitle: '123'},
];
the desired output of updating duplicates:
[
{id: '1', collectionTitle: '456'},
{id: '2', collectionTitle: '123 (0)'},
{id: '3', collectionTitle: '123 (1)'},
];
CodePudding user response:
First I group by the title so I can count how many of each. I use the famous array reduce method for that. Then use that grouped object to reconstruct the names.
var arrayCollection = [
{id: 1, collectionTitle: "Hello"},
{id: 2, collectionTitle: "Goodbye"},
{id: 3, collectionTitle: "Hello"},
];
var obj = arrayCollection.reduce(function(agg, item) {
agg[item.collectionTitle] = agg[item.collectionTitle] || []
agg[item.collectionTitle].push(item)
return agg;
}, {})
var result = [];
Object.values(obj).forEach(function(arr) {
if (arr.length == 1) {
result.push(arr[0])
} else {
for (var i = 0; i < arr.length; i ) {
arr[i].collectionTitle = " (" i ")";
result.push(arr[i])
}
}
})
console.log(result)
CodePudding user response:
One of the fastest and most customizable ways to do this:
let result = [];
let dup = {}
for (let x = 0; x < arr.length; x ){
if (dup[arr[x]]) {
result.push(‘whatever u want’);
} else {
result.push(arr[x]);
dup[arr[x]] = true;
}
}
CodePudding user response:
If you don't mind that first duplicate is not labelled, this will work:
const input = [
{id: '1', collectionTitle: '456'},
{id: '2', collectionTitle: '123'},
{id: '3', collectionTitle: '123'},
]
const result = input.map((current, i, array) => {
// Number of duplicates so far
const duplicatesCount = array
.slice(0, i)
.filter(el => el.collectionTitle.startsWith(current.collectionTitle))
.length
return {
id: current.id,
collectionTitle: duplicatesCount > 0
? `${current.collectionTitle} (${duplicatesCount})`
: current.collectionTitle,
}
})
console.log(result)
It is not a good solution performance-wise (nested .slice
and .filter
inside .map
), but the code itself is relatively concise.