1
var items = [{
    "name": "James",
    "gender": "boy"
}, {
    "name": "Sam",
    "gender": "boy"
}, {
    "name": "Alice",
    "gender": "girl"
}];

I want to add count for the gender into a array of object above. like for boy it's 2, and girl it's 1. I've done below part where it return the category.

var genderList = [];
for(var i = 0; i < items.length ; i++){
      if(genderList.indexOf(items[i].gender) < 0){
        genderList.push(items[i].gender);
       }
}

how can I produce the result like this?

[{"name":"boy","count":2},{"girl","count":1}]
2
  • 2
    The desired result isn't valid JS, because the "girl" part has a property name with no value (or value with no property name). Why wouldn't you just use {"boy": 2, "girl": 1} instead of an array? Commented Mar 3, 2017 at 4:15
  • I'm a little late to the game but hoping my comments will help you understand what's happening! Commented Mar 3, 2017 at 5:01

3 Answers 3

1

You can use the array .reduce() method to count values - I'd suggest getting output in a structure like {"boy": 2, "girl": 1} rather than the array of objects you showed, because it's simple and efficient to create, update, and read.

You could then convert it to the format you've shown:

var items = [
  { "name": "James", "gender": "boy"},
  { "name": "Sam", "gender": "boy"},
  { "name": "Alice", "gender": "girl"}
];

var genderCount = items.reduce(function(a, c) {
  a[c.gender] = (a[c.gender]||0) + 1;
  return a;
}, {});
console.log(JSON.stringify(genderCount));

var asArray = Object.keys(genderCount).map(v => ({ name: v, count: genderCount[v] }));
console.log(JSON.stringify(asArray));

If you're not familiar with .reduce(), it does the same thing as the loop below, except without needing to create extra working variables in the current scope:

var items = [
  { "name": "James", "gender": "boy"},
  { "name": "Sam", "gender": "boy"},
  { "name": "Alice", "gender": "girl"}
];

var genderCount = {}
for (var i = 0; i < items.length; i++) {
  genderCount[items[i].gender] = (genderCount[items[i].gender]||0) + 1;
}
console.log(JSON.stringify(genderCount));

// then as above to get your array of objects output:
var asArray = Object.keys(genderCount).map(v => ({ name: v, count: genderCount[v] }));
console.log(JSON.stringify(asArray));

NOTE: In the above examples I'm using JSON.stringify() only to make it fit in the console on one line, it's not part of the counting/conversion process.

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

3 Comments

At for loop example, OP appears to expect an array of objects as result.
@guest271314 - I ended up adding that part to the second block after all. That format makes no sense to me, unless maybe it is going to be input to some graphing function or something like that, but it is what she asked for. Either way I think it is more efficient to create the intermediate {"boy":2,"girl":1} object first and then map it, rather than trying to find and update values in an array during the counting phase.
@Mellisa - I've used "a" for "accumulator" and "c" for "current value". I think it's readable for folks who are familiar with .reduce() because they're part of the standard .reduce() behaviour. If the function were long and complicated I might use acc and val or even accumulator and currentVal, but this is a one-liner plus return statement with no other local variables, so... (Some people use "p" for "previous" instead of "a", depending on context.)
1
var items = [
  { "name": "T", "gender": "other"},
  { "name": "James", "gender": "boy"},
  { "name": "Sam", "gender": "boy"},
  { "name": "Alice", "gender": "girl"}
];

taking the previous item and comparing the gender type. If it exists we add 1, if doesn't then we create it and add 1.

var genderTypes = items.reduce(function(prev, cur) {
  prev[cur.gender] = (prev[cur.gender]||0) + 1;
  return prev;
}, {});

console.log('genderTypes', genderTypes)

next we take the keys from the object and separate them out into gender and count

var separateNameAndCount = Object.keys(genderTypes).map(type => ({ name: type, count: genderTypes[type] }));

console.log('separateNameAndCount', separateNameAndCount)

finally we convert the object to json format

console.log(JSON.stringify(separateNameAndCount));

Comments

0

Try like this.use Array.map

var items = [{
    "name": "James",
    "gender": "boy"
}, {
    "name": "Sam",
    "gender": "boy"
}, {
    "name": "Alice",
    "gender": "girl"
}];
var b=0,g=0;
items.map((item)=>(item.gender=="boy")?b++:g++);
var finalArray = [{"name":"boy","count":b},{"name":"girl","count":g}]
console.log(finalArray);

3 Comments

If you're not doing anything with the return value from .map() you should be using .forEach().
what if I have another kind of gender?this solution is not flexible.
You can manage this using if else if .. conditions instead of ternary operator.

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.