1

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
    }
]
5
  • Can you provide a sample of what phases contain?? Commented Feb 21, 2018 at 20:28
  • Added to the main post ^^^ Commented Feb 21, 2018 at 20:31
  • are you sure you want to store your data in an array such as [phase_number, id]? My guess is that it would be better to push({phase_number: phases[i].phase_number, id: phases[i].id}) Commented Feb 21, 2018 at 20:32
  • That's not valid json... you have two "id" attributes. Commented Feb 21, 2018 at 20:33
  • That's not it, I just changed the lines here. They have different keys. Commented Feb 21, 2018 at 20:34

3 Answers 3

4

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
}
Sign up to request clarification or add additional context in comments.

5 Comments

I think since Set will be unique anyway, the .has() check isn't necessary, but perhaps the ES6 Map obj might be more suitable.
I'm using the Set to check if an id already exists when filtering the array. I'm not returning the Set as the result.
That's awesome! Thanks so much. I added some keys as well, but this is great
@MattLarson - welcome :) I've added another solution that uses Map and reduce.
So slick. I really appreciate it!
0

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
  })
}

Comments

0

I would leverage lodash for this: https://lodash.com/docs#sortedUniqBy

salesPhases () {
  return _.sortedUniqBy(this.$store.state.addresses.salesPhases, 
    phase => phase.phase_number)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.