0

I'm trying to count similar array values to get how many quantities of similar items there are in array. I managed to get the counts however I want to show every quantities in the array in HTML

var arr = ['Coke','Coke Diet','Pepsi','Sprite','Coke','Water'];
var obj = [];
for (var i = 0, j = arr.length; i < j; i++) {
   if (obj[arr[i]]) {
      obj[arr[i]]++;
   }
   else {
      obj[arr[i]] = 1;
   } 
}

I'm having a problem to render them in HTML without specifying what type of drink.

$('#items').append(obj.Coke)

How can I .append(obj) without saying what kind of drink I want to show?

I want to show something like -- (quantity) (drink)

2x Coke
1x Sprite
3x Water

JSfiddle sample

Edit -- both answers below works, but I have another question regarding this. How can I prevent rendering the same item when adding an item to array instead just want to update the quantity when you hit add button.

I've created a new fiddle for this follow up question.

End Result should look like --

1 Coke
2 Sprite

rather than

1 Coke 1 Sprite 2 Sprite

JsFiddle 2 sample

5
  • var obj = []; should be var obj = {}; Commented Feb 16, 2017 at 2:10
  • @hackerrdave I tried that as well but its not appending the counts unless i put obj.Coke Commented Feb 16, 2017 at 2:11
  • I'm a little confused as to what you want to do - do you want to dynamically grab properties from obj? Commented Feb 16, 2017 at 2:13
  • Yes, that's right. Commented Feb 16, 2017 at 2:15
  • You can access values from object via obj['Coke'] - so just iterate thru the keys and pass that value in to the obj - obj[key] where key = 'Coke'. Also see the answer added below Commented Feb 16, 2017 at 2:17

2 Answers 2

3

First of all obj should be an object {} not an array [].

Second, to loop through the keys of an object, use Object.keys like this:

Object.keys(obj).forEach(function(key) {
    var str = obj[key] + "x " + key;
    $('#items').append(str);
}

Note:

If you don't want to use forEach, you can iterate through the object keys using a for-in like this:

for(var key in obj) {
    var str = obj[key] + "x " + key;
    $('#items').append(str);
}

Example:

In this example I used reduce and forEach because they're better.

var arr = ['Coke','Coke Diet','Pepsi','Sprite','Coke','Water'];

var obj = arr.reduce(function(o, e) {
  if(o[e]) o[e]++;
  else o[e] = 1;
  return o;
}, {});

Object.keys(obj).forEach(function(key) {
  var str = obj[key] + "x " + key;
  $("<li></li>").text(str)
                .appendTo("#items");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="items"></ul>

Edit:

You can acheive what you asked in the edit of your question in two ways:

  1. Every time the button get clicked, empty the .cart element and refill it with the new statistics. Like this: https://jsfiddle.net/z02z51pm/.
  2. When adding the item to the list, set a an ID (something like count-of-Coke ...), so when a new item is added, we only update the row of that item without affecting the other rows. This is very useful if the list is very big, because instead of emptying the .cart element and rebuild it from scratch, we only update the row of the item using that ID. Like this: https://jsfiddle.net/ppesc6ek/.

Note that I changed a bit of your code, havink an array to store the items and then count the items inside it every time, is a hell of a labor, what I did instead is get rid of those two arrays and replace them with the counter object directly, so when an item is added, we won't recount the items we already counted, but instead we will just increment the counter of that item (or create a new one if that item haven't been added yet).

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

15 Comments

can I ask?. what does this line do?. if(o[e]) o[e]++;
@fauxserious read this. It's a great chapter about why functional is better!
@KiRa Here is a link to a great book, you may find it useful.
@MrNew See the Edit section above!
@MrNew That's because I'm making an ID out of the name, but IDs must not have spaces count-of-Diet Coke is not valid. Here I fixed it by replacing the spaces with -. Check it here jsfiddle.net/ppesc6ek/4!
|
1

You can try with below solution:

var arr = ['Coke','Coke Diet','Pepsi','Sprite','Coke','Water'];
var obj = {};
for (var i = 0, j = arr.length; i < j; i++) {
   if (obj[arr[i]]) {
      obj[arr[i]]++;
   }
   else {
      obj[arr[i]] = 1;
   } 
}

show = function() {
  Object.keys(obj).map(function(drink){
    var info = obj[drink]+"x "+drink+"<br/>";
    $('#items').append(info)
  })
}

3 Comments

Thanks, this works bril. I have a follow up question please see my original question. Trying to prevent rendering the same item everytime I hit add btn, It's probably because of the .append() but instead I just want to update the quantity rather than having the same items but different quantities each time it renders
Can you try with $('#items').html(info) instead of .append() method.
yeah did that and that will only add 1 item click, what I want is (1) Coke, (2) Sprite rather than (1) Coke, (1)Sprite, (2) Sprite

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.