0

I'm able to successful produce a new array containing only the unique values, but I can't get my count function to work. I want the result to show how many items in the array have each color.

My desired result would be:

4 red
10 blue
1 green

Currently the result is a count of 0 for each color. I'm assuming this might have something to do with me adding the count property when I map the array to a new variable.

The reason I wrapped it in the if (loopComplete == false) condition is because I was getting undefined errors and was trying to make sure that the second for loop was running after the first was complete.

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) {
      let newArray = array.map(function(item) {
        return {
          'color': item.color,
          'count': 0,
        };
      });
      let arrayUnique = [];
      let arrayAdded = [];
      let loopComplete = false;

      if (loopComplete == false) {
        for (let i = 0; i < newArray.length; i++) {
          if (!arrayAdded.includes(newArray[i].color)) {
            arrayAdded.push(newArray[i].color);
            arrayUnique.push(newArray[i]);
          }
        }
        loopComplete = true;
        return arrayUnique;
      } else {
        for (let i = 0; i < newArray.length; i++) {
          if (arrayUnique.includes(newArray[i].color)) {
            arrayUnique[i].count++;
          }
          return arrayUnique;
        }
      }
    }
  }
});
<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>

3 Answers 3

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>

Sign up to request clarification or add additional context in comments.

Comments

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>

1 Comment

Brilliant! Thanks!
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]
}, [])

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.