[Vuejs]-Vue method to count duplicates in array

2πŸ‘

βœ…

One way is to use a for loop.

var vm = new Vue({
  el: '#app',
  data: {
    myArray: [
      { color: 'red',
        number: '1'
      },
      {
        color: 'red',
        number: '2'
      },
      {
        color: 'red',
        number: '3'
      },
      {
        color: 'red',
        number: '4'
      },
      {
        color: 'blue',
        number: '5'
      },
      {
        color: 'blue',
        number: '6'
      },
      {
        color: 'blue',
        number: '7'
      },
      {
        color: 'blue',
        number: '8'
      },
      {
        color: 'blue',
        number: '9'
      },
      {
        color: 'blue',
        number: '10'
      },
      {
        color: 'blue',
        number: '11'
      },
      {
        color: 'blue',
        number: '12'
      },
      {
        color: 'blue',
        number: '13'
      },
      {
        color: 'blue',
        number: '14'
      },
      {
        color: 'green',
        number: '15'
      },
    ],
  },
  computed: {
    filteredArray() {
      var ret = {}
      for (let i in this.myArray) {
        let key = this.myArray[i].color
        ret[key] = {
           color: key,
           count: ret[key] && ret[key].count ? ret[key].count + 1 : 1
        }
      }
      return Object.values(ret)
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="result in filteredArray">
    {{ result.count }} {{ result.color }}
  </div>
  <pre>{{filteredArray}}</pre>
</div>

2πŸ‘

Rather than using conditional logic (and .includes()), you could transform the array into a map using .reduce(), the result of which would look like this:

{
  red: 4,
  blue: 10,
  green: 1
}

From there, you could .map() it into your desired shape.

var vm = new Vue({
  el: '#app',
  data: {
    myArray: [ { color: 'red', number: '1' }, { color: 'red', number: '2' }, { color: 'red', number: '3' }, { color: 'red', number: '4' }, { color: 'blue', number: '5' }, { color: 'blue', number: '6' }, { color: 'blue', number: '7' }, { color: 'blue', number: '8' }, { color: 'blue', number: '9' }, { color: 'blue', number: '10' }, { color: 'blue', number: '11' }, { color: 'blue', number: '12' }, { color: 'blue', number: '13' }, { color: 'blue', number: '14' }, { color: 'green', number: '15' }, ],
  },
  computed: {
    filteredArray() {
      return this.count(this.myArray);
    }
  },
  methods: {
    count(array) {
      //add 1 if the color exists, initialize as 1 if it does not
      let counts = array.reduce((out, {color}) => ({ ...out, [color]: out[color]+1 || 1}), {});
      return Object.keys(counts).map(key => ({color: key, count: counts[key]}));
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="result in filteredArray">
    {{ result.count }} {{ result.color }}
  </div>
</div>
πŸ‘€Tyler Roper

1πŸ‘

You should first get all colors using arr.map():

const allColors = myArray.map(item => item.color);

Then you shoud just count each color in this array:

let colors = {};
for (let i = 0; i < allColors.length; i++) {
    colors[allColors[i]] = (colors[allColors[i]] + 1) || 1;
}

And your filteredArray would be:

filteredArray = Object.keys(colors).reduce((acc, cur) => {
    acc.push({color: cur, result: colors[cur]});
    return [...acc]
}, [])

Leave a comment