使用.map将数量转换为百分比

时间:2015-04-26 01:58:54

标签: javascript underscore.js lodash

我想使用Javascript的lodash将这个数组对象转换为百分比。这是对象:

gender = { 
  female: [14, 33, 28, 49],
  male: [33, 50, 42, 61]
}

我希望上面的对象是

genderPercent = { 
  female: [0.2978, 0.3975, ..., ...],
  male: [0.7021, 0.6024, ..., ...]
}

这是我已经尝试过的:

_.map(gender, function (val, index, list) {
  gender["male"][gender["male"].length-1] / gender["male"][gender["male"].length-1] + gender["female"][gender["female"].length-1])
});

但这似乎不起作用。

有什么建议吗? :)

(注意:我需要随时间推移的解决方案,因为我的性别数组每个月都会持续增长。)

4 个答案:

答案 0 :(得分:2)

如果男性和女性的长度始终相同,您可以使用for循环:

var gender = { 
  female: [14, 33, 28, 49],
  male: [33, 50, 42, 61]
}
var m = gender.male;
var f = gender.female;

var genderP = {female:[], male:[]};
for (var i = 0; i < gender.female.length; i++) {
  var t = m[i] + f[i];
  genderP.male.push(m[i]/t);
  genderP.female.push(f[i]/t);
}

console.log(JSON.stringify(genderP, null, 2));
/*
{
  "female": [
    0.2978723404255319,
    0.39759036144578314,
    0.4,
    0.44545454545454544
  ],
  "male": [
    0.7021276595744681,
    0.6024096385542169,
    0.6,
    0.5545454545454546
  ]
}
*/

_.zip_.unzip也可以使用:

var gender = { 
  female: [14, 33, 28, 49],
  male: [33, 50, 42, 61]
}

var genderP = _.zipObject(['male', 'female'], _.chain(_.zip(gender.male, gender.female))
  .map(function(pair) {
    var t = pair[0] + pair[1]
    return [pair[0] / t, pair[1] / t]
  })
  .unzip()
  .value());

console.log(JSON.stringify(genderP, null, 2));
/*
{
  "male": [
    0.7021276595744681,
    0.6024096385542169,
    0.6,
    0.5545454545454546
  ],
  "female": [
    0.2978723404255319,
    0.39759036144578314,
    0.4,
    0.44545454545454544
  ]
}
*/
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.7.0/lodash.min.js"></script>

答案 1 :(得分:2)

仅仅for循环怎么样?

var genderPercent = { male: [], female: [] );
for (var i=0; i<gender.male.length && i<gender.female.length; i++)
{
    malePercent = gender.male[i] / (gender.male[i] + gender.female[i]);
    genderPercent.male.push(malePercent);
    genderPercent.female.push(1 - malePercent);
}
编辑:刚看到你的笔记。这个解决方案不会这样做,但我认为不可能在不到线性的时间内完成。你必须对每一个进行计算。

编辑2:实际上线性时间非常可扩展;我不担心。

答案 2 :(得分:1)

这对你有什么影响?我认为它符合你的要求。

var genders = { 
  female: [14, 33, 28, 49],
  male: [33, 50, 42, 61]
};

var percents = _.map(genders, function(gender_val, gender) {
  return _.map(gender_val, function(val, i) {
    var opposite = gender == "male" ? "female" : "male";
    return val / (val + genders[opposite][i]);
  });
});
var genderPercents = _.zipObject(_.keys(genders), percents);
console.log(genderPercents);

输出以下内容:

Object {female: Array[4], male: Array[4]}
  female: Array[4]
    0: 0.2978723404255319
    1: 0.39759036144578314
    2: 0.4
    3: 0.44545454545454544
  male: Array[4]
    0: 0.7021276595744681
    1: 0.6024096385542169
    2: 0.6
    3: 0.5545454545454546

答案 3 :(得分:0)

如果你真的想使用数组理解(在本例中是原生的,而不是下划线),你可以这样做:

var gender = { 
  female: [14, 33, 28, 49],
  male: [33, 50, 42, 61]
};

var genderPercent = gender.female.reduce(function(p,c,i,a) {
    var f = p.female[i];
    var m = p.male[i];
    var sum = f+m;
    p.female[i] = f/sum;
    p.male[i] = m/sum;
    return p;
}, gender);

如果女性和男性名单的长度不同,这将失败。

此外,它不会像每月保留结果和追加新百分比那样扩展,而不是每次都重新计算所有这些。