admin管理员组

文章数量:1387421

So I'm trying to think of a better way to do this with underscore:

state.attributes = _.reduce(list, function(memo, item){ 
    memo['neighborhood'] = (memo['neighborhood'] || []);
    var isNew = true;
    _.each(memo['neighborhood'], function(hood){
        if (hood.name === item.data.neighborhood) {
            hood.count++; isNew=false;
        } 
    });
    if(isNew){
        memo['neighborhood'].push({name:item.data.neighborhood, count:1});
    }
    return memo;
});

I would like to bine the various names of the list into a list of unique names with a count of how many times each unique name occurs. It seems like exactly the kind of problem underscore was designed to solve, yet the best solution I could think of seems less than elegant.

So I'm trying to think of a better way to do this with underscore:

state.attributes = _.reduce(list, function(memo, item){ 
    memo['neighborhood'] = (memo['neighborhood'] || []);
    var isNew = true;
    _.each(memo['neighborhood'], function(hood){
        if (hood.name === item.data.neighborhood) {
            hood.count++; isNew=false;
        } 
    });
    if(isNew){
        memo['neighborhood'].push({name:item.data.neighborhood, count:1});
    }
    return memo;
});

I would like to bine the various names of the list into a list of unique names with a count of how many times each unique name occurs. It seems like exactly the kind of problem underscore was designed to solve, yet the best solution I could think of seems less than elegant.

Share Improve this question edited May 6, 2012 at 8:31 BishopZ asked May 6, 2012 at 7:58 BishopZBishopZ 6,3888 gold badges47 silver badges60 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

I'm not an underscore.js user, but I guess _.groupBy() suits this scenario:

var attributes = _.groupBy(list, function (item) {
    return item.data.neighborhood
})

It doesn't returns an array in the exact way you want, but it contains all the information you need. So you have in attributes["foo"] all the items that have "foo" as neighborhood value property, and therefore in attributes["foo"].length the count of them.

Maybe there is a better underscore.js way, but you can already apply other optimizations:

Instead of using an array to keep track of the name and the count, use a name: count map. This can be easily done with an object:

state.attributes = _.reduce(list, function(memo, item){ 
    var n = item.data.neighborhood;
    memo['neighborhood'] = (memo['neighborhood'] || {});
    memo['neighborhood'][n] = memo['neighborhood'][n] + 1 || 1;
    return memo;
});

This works, because if item.data.neighborhood is not in the list yet, memo['neighborhood'][item.data.neighborhood] will return undefined and undefined + 1 returns NaN.
Since NaN evaluates to false, the expression NaN || 1 will result in 1.

本文标签: javascriptcounting object properties with underscorejsStack Overflow