'Code works (mostly). But failure to remove duplicates
Summary:
Hey I've got a filter for some data. It's filtering fine but it's not removing duplicate objects. Arguments taken in order:
1. datasource
2. filters (remove all matching)
3. unique: (whether to remove duplicate items)
4. prop ( object properties - used for Listing a an attribute of unfiltered items - not in use))
Data:
var moduleData = [
{manufacturer: "SunPower Corp.", productNo: "SPR-M475-COM-MLSD", watts: 475, cells: 72, warranty: 25, degradation: 0, volume: 0, smartModule: false, adder: 0, available: true},
{manufacturer: "TestCo", productNo: "TE-STc001", watts: 475, cells: 72, warranty: 25, degredation: 0, volume: 0, smartModule: false, adder: 0, available: true},
{manufacturer: "TestCo", productNo: "TE-STc001", watts: 475, cells: 72, warranty: 25, degredation: 0, volume: 0, smartModule: false, adder: 0, available: true},
{manufacturer: "TestCo", productNo: "TE-STc002", watts: 475, cells: 72, warranty: 25, degredation: 0, volume: 0, smartModule: false, adder: 0, available: true},
{manufacturer: "TestCo", productNo: "TE-STc002.5", watts: 475, cells: 72, warranty: 25, degredation: 0, volume: 0, smartModule: false, adder: 0, available: true},
{manufacturer: "TestCoDuplicate", productNo: "TE-STc002.5", watts: 430, cells: 71, warranty: 23, degredation: 2, volume: 1, smartModule: true, adder: 5, available: true},
{manufacturer: "TestCo", productNo: "TE-STc003", watts: 475, cells: 72, warranty: 25, degredation: 0, volume: 0, smartModule: false, adder: 0, available: true},
]
Function:
const filters = {}
const getFilteredArray = ((data, filters, isItUnique, prop ) => {
//Arrays
// filtered Array =======================================
if ((prop.length > 0 || prop != undefined || prop != null) && (prop.length == 0 || prop == undefined || prop == null)){
let nonUniqueArray = data.filter(p =>
filters.every(f=> Object.keys(f).every(k => p[k] === f[k]))
)
console.log('filtered Array - (unique, no prop) ')
var unique = []
//XXXXXXXXXXXXX make array unique XXXXXXXXXXXXXXXXX
const uniqueArray = nonUniqueArray.filter(element => {
const isDuplicate = unique.includes(element);
if (!isDuplicate) {
unique.push(element)
return true
}
})
return uniqueArray
}
})
filters.available = true
filters.manufacturer = "TestCo"
//console.log(filters)
console.log(getFilteredArray(moduleData, [filters], "unique", "" ))
So I'm looking for products with a manufacturer of TestCo, that's available and looking to remove duplicates.
ITS RETURNING:
Console:[Object, Object, Object, Object, Object] (5)<br>
0 {manufacturer: "TestCo", productNo: "TE-STc001", watts: 475, cells: 72, warranty: 25, …}<br>
1 {manufacturer: "TestCo", productNo: "TE-STc001", watts: 475, cells: 72, warranty: 25, …}<br>
2 {manufacturer: "TestCo", productNo: "TE-STc002", watts: 475, cells: 72, warranty: 25, …}<br>
3 {manufacturer: "TestCo", productNo: "TE-STc002.5", watts: 475, cells: 72, warranty: 25, …}<br>
4 {manufacturer: "TestCo", productNo: "TE-STc003", watts: 475, cells: 72, warranty: 25, …}<br>
Its clear you can see prod No TE-STc001 twice. (not removed). Being a complete copy, I would think one of them wouldn't be added to the uniqueArray. Why is that and how can I fix my code? Thanks in advance!
Solution 1:[1]
Depending on your use case you can remove duplicate objects from your array in several ways.
1.) Filter duplicates by one object property
const uniqueData = moduleData.filter((v,i,a) => a.findIndex(v2 => (v2.productNo === v.productNo)) === i)
2.) Filter by several properties
const uniqueData = moduleData.filter((v,i,a) => a.findIndex(v2 => ['productNo','manufacturer'].every(k => v2[k] === v[k])) === i)
3.) Check all properties and filter duplicates (if you know the quality of your data this is likely overkill)
const uniqueData = moduleData.filter((v,i,a) => a.findIndex(v2 => [...Object.keys(moduleData[0])].every(k => v2[k] === v[k])) === i)
In the second half of your solution instead of looking again for duplicates within the list after you create an array of object properties for your dropdown values the way you are, you can easily filter out duplicates by simply using the Set constructor and the spread syntax
doubleUniquePropList = [...new Set(uniquePropList)]
Solution 2:[2]
So, I found the solution:
It seemed to make the difference to stringify the object and then compare. And I took the advice of jFriend00 and removed duplicates first before filtering.
The solution:
// filtered Array =======================================
if ((prop.length > 0 || prop != undefined || prop != null) && (prop.length == 0 || prop == undefined || prop == null)){
console.log('filtered Array - (unique, no prop) ')
//Make data unique
const uniqueArray = data.filter((object,index) => index === data.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object)));
return uniqueArray
}
... and that made it not all that difficult then to provide filtered Lists as well. (for dropdowns.)
// filtered List =======================================
if ((prop.length > 0 || prop != undefined || prop != null) && (prop.length !== 0 || prop.length !== undefined || prop.length !== null)){
console.log('filtered List - (unique, prop) ')
//Make data unique
const uniqueArray = data.filter((object,index) => index === data.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object)));
//filter the list for matches
let UniqueArray = uniqueArray.filter(p =>
filters.every(f=> Object.keys(f).every(k => p[k] === f[k]))
)
//map Array into the desired list
let uniquePropList = UniqueArray.map(item => item[prop])
//look again for duplicates within the list
var unique = []
let doubleUniquePropList = uniquePropList.filter(element => {
const isDuplicate = unique.includes(element);
if (!isDuplicate) {
unique.push(element)
return true
}
})
return doubleUniquePropList
}
Now I can use this function for many different use cases! Thank you guys for your help! and I hope this can help someone else!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | CaseyC |
| Solution 2 | Michael Martell |
