使用underscore.js计算对象属性

时间:2012-05-06 07:58:07

标签: javascript underscore.js

所以我试图用下划线来考虑更好的方法:

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;
});

我想将列表的各种名称组合成一个唯一名称列表,其中包含每个唯一名称出现次数的计数。看起来正是下划线设计要解决的那种问题,但我能想到的最佳解决方案似乎并不优雅。

2 个答案:

答案 0 :(得分:5)

我不是一个underscore.js用户,但我猜_.groupBy()适合这种情况:

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

它不会以您想要的方式返回数组,但它包含您需要的所有信息。因此,您在attributes["foo"]中的所有项目中都有“foo”作为neighborhood值属性,因此在attributes["foo"].length中包含了{{1}}的计数。

答案 1 :(得分:1)

也许有更好的underscore.js方式,但您已经可以应用其他优化:

使用name: count地图,而不是使用数组来跟踪名称和计数。这可以通过对象轻松完成:

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;
});

这样做有效,因为如果列表中尚未显示item.data.neighborhoodmemo['neighborhood'][item.data.neighborhood]将返回undefinedundefined + 1会返回NaN。 由于NaN评估为false,因此表达式NaN || 1将导致1