Reputation: 1519
I have an array of objects coming to my Vuejs front-end via api call and I am attempting to loop through, remove duplicates, then return a new array with unique "phases" and their associated "id's". The original array has several other key/values I do not need. I am also sorting them in order by the phase number. Here's my code:
salesPhases () {
let phases = this.$store.state.addresses.salesPhases
let uniquePhases = []
for (let i = 0; i < phases.length; i++) {
if (uniquePhases.indexOf(phases[i].phase_number) === -1) {
uniquePhases.push(phases[i].phase_number)
}
}
return uniquePhases.sort((a, b) => {
return a - b
})
}
The above code works for everything I need, minus including the id
. Here's my attempt at doing that, which then negates the unique phases condition.
uniquePhases.push([phases[i].phase_number, phases[i].id])
The sort still works, but it is then sorting one big single-dimensional array. The array of phases looks something like this:
{ "data": [
{
"id": "94e224af-135f-af31-3619-535acfae9930",
"street_address1": "407 48TH ST E",
"street_address2": null,
"phase": "101",
"sales_rep": "164",
"id": "abd90d6b-28a8-2be6-d6c1-abd9007aef38",
"name": "48TH ST E",
"block_minimum": 400,
"block_maximum": 498,
"side": 2
},
{
"id": "94e224af-135f-af31-3619-535acfae9930",
"street_address1": "407 48TH ST E",
"street_address2": null,
"phase": "101",
"sales_rep": "164",
"id": "abd90d6b-28a8-2be6-d6c1-abd9007aef38",
"name": "48TH ST E",
"block_minimum": 401,
"block_maximum": 499,
"side": 1
}
]
Upvotes: 1
Views: 1483
Reputation: 192016
You can filter the array to get only unique, using a Set, then map the items into new objects that contain only the id
and the phase_number
, and then sort by the phase_number
:
salesPhases () {
const uSet = new Set()
return this.$store.state.addresses.salesPhases
.filter(({ phase_number }) => uSet.has(phase_number) ? false : uSet.add(phase_number)) // get uniques by phase_number
.map(({ id, phase_number }) => ({ id, phase_number })) // get an object with the id and the phase_number
.sort((a, b) => a.phase_number - b.phase_number) // sort by phase_number
}
You can also use reduce and Map, and then spread the Map.values()
iterator to an array
salesPhases () {
return [...this.$store.state.addresses.salesPhases
.reduce((m, { id, phase_number }) =>
m.has(phase_number) ? m : m.set(phase_number, { id, phase_number }), new Map()) // set to map, if phase_number key doesn't exist
.values()] // convert the Map values to an array
.sort((a, b) => a.phase_number - b.phase_number) // sort by phase_number
}
Upvotes: 4
Reputation: 2312
I would leverage lodash for this: https://lodash.com/docs#sortedUniqBy
salesPhases () {
return _.sortedUniqBy(this.$store.state.addresses.salesPhases,
phase => phase.phase_number)
}
Upvotes: 0
Reputation: 180
One solution is to update your code to push the entire phase object, rather than just the phase number, and then use the Array find
method instead of indexOf
, to check if a phase with the given number is found.
Try this:
salesPhases () {
let phases = this.$store.state.addresses.salesPhases
let uniquePhases = []
for (let i = 0; i < phases.length; i++) {
if (!uniquePhases.find(x => x.phase_number === phases[i].phase_number)) {
uniquePhases.push(phases[i])
}
}
return uniquePhases.sort((a, b) => {
return a.phase_number - b.phase_number
})
}
Upvotes: 0