Javascript 使用lodash查找平均值的最有效方法

Javascript 使用lodash查找平均值的最有效方法,javascript,underscore.js,lodash,Javascript,Underscore.js,Lodash,我有一个对象数组,对象的数量是可变的- var people = [{ name: john, job: manager, salary: 2000 }, { name: sam, job: manager, salary: 6000 }, { name: frodo, job: janitor }]; 找到使用lodash的所有经理的平均工资的最优雅的方法是什么?(我假设我们必须检查对象是否为经理,以及对象是否具有薪资属性) 我在想下面的话- _(pe

我有一个对象数组,对象的数量是可变的-

var people = [{
  name: john,
  job: manager,
  salary: 2000
},
  {
  name: sam,
  job: manager,
  salary: 6000
},
  {
  name: frodo,
  job: janitor
}];
找到使用lodash的所有经理的平均工资的最优雅的方法是什么?(我假设我们必须检查对象是否为经理,以及对象是否具有薪资属性)

我在想下面的话-

_(people).filter(function(name) {
    return name.occupation === "manager" && _(name).has("salary");}).pluck("salary").reduce(function(sum,num) { return sum+num });
但我不确定这是否是正确的方法。

“高效”是一个非常模糊的术语。说到“高效”,你可以考虑性能、可读性、简洁性等等。我认为最具可读性和简洁性的解决方案是:

_(people).filter({ job: 'manager'}).filter('salary').reduce(function(a,m,i,p) {
    return a + m.salary/p.length;
},0);
最快的解决方案是根本不使用loadash、任何库、任何
过滤器
减少
方法。将
用于
循环:

var sum    = 0;
var count  = 0;
for (var i = 0, ii = people.length; i < ii; ++i) {
    var man = people[i];

    if (typeof man.salary !== 'undefined') {
        sum += man.salary;
        ++count;
    }
}
var avg = sum/count;
var总和=0;
var计数=0;
对于(变量i=0,ii=people.length;i

我认为在大多数情况下,对于客户端开发来说,可读性比性能更重要,因此我认为第一个变体是最“有效的”。

我不知道Lowdath,但也许一个简单的JS解决方案可以帮助您实现这一目标:

console.log(people.reduce(function(values, obj) {
              if (obj.hasOwnProperty('salary')) {
                values.sum += obj.salary;
                values.count++;
                values.average = values.sum / values.count;
              }
              return values;
            }, {sum:0, count:0, average: void 0}).average
); // 4000
这将传递一个要减少的对象作为累加器,该累加器具有三个属性:工资总额、工资计数和迄今为止的平均值。它对所有对象进行迭代,将工资相加,计算有多少工资,并计算每次迭代的平均值。最终,它返回该对象(累加器),并读取平均属性

调用单个内置方法应该比调用4个本机函数更快(即更高效)。“优雅”在旁观者的眼里

顺便说一句,对象文字中有错误,应该是:

var people = [{
  name: 'john',
  job: 'manager',
  salary: 2000
},
  {
  name: 'sam',
  job: 'manager',
  salary: 6000
},
  {
  name: 'frodo',
  job: 'janitor'
}];
我能想到的最干净(优雅)的方式是:

var salariesOfManagers = _(people).filter({job: 'manager'}).filter('salary').pluck('salary');
var averageSalary = salariesOfManagers.sum() / salariesOfManagers.value().length;
它取项目之和,然后除以项目数,这几乎就是平均数的定义


太糟糕了,如果你想让它整洁一行,代码将变得不那么清晰。

使用功能更强大的
lodash
版本(
lodash fp
)和
es2015
,你可以使用箭头功能和自动咖喱来获得更灵活、更功能化的解决方案

function average(acc, ele, index) {
    return (acc + ele) / (index + 1);
}

var result = _.chain(people)
    .filter('job', 'manager')
    .map('salary')
    .reduce( average )
    .value();
你可以把它放在一行难看的单字里:

const result = _.flow(_.filter(['job', 'manager']), 
    e => _.sumBy('salary', e) / _.countBy(_.has('salary'), e).true)(people);
或者您可以创建一个整洁的DSL:

const hasSalary = _.has('salary');
const countWhenHasSalary = _.countBy(hasSalary);
const salarySum = _.sumBy('salary');
const salaryAvg = a => salarySum(a) / countWhenHasSalary(a).true;
const filterByJob = job => _.filter(['job', job]);
const salaryAvgByJob = job => _.flow(filterByJob(job), salaryAvg);

const result = salaryAvgByJob('manager')(people);
使用和ES2016/ES6,可以以更有效的方式完成

const avg = flow(
    filter({job: 'manager'}), 
    map('salary'),
    mean
)

console.log(avg(people))
你所做的是 1.获取所有对象的“管理器”类型 2.从中提取“薪资”属性/字段 3.用均值函数求平均值

下面是一个完整版本的代码,为了方便您,它运行在nodejs上

'use strict'
const _ = require('lodash/fp');

const {
    flow,
    filter,
    map,
    mean
} = _

const people = [{
    name: 'john',
    job: 'manager',
    salary: 2000
}, {
    name: 'sam',
    job: 'manager',
    salary: 6000
}, {
    name: 'frodo',
    job: 'janitor'
}];

const avg = flow(
    filter({job: 'manager'}), 
    map('salary'),
    mean
)

console.log(avg(people))

为什么这里的人都很复杂

const people=[
{名称:'Alejandro',预算:56},
{名称:'Juan',预算:86},
{名称:“佩德罗”,预算:99},
];
const average=u.meanBy(人,(p)=>p.budget);
控制台日志(平均值)
lodash v3:

\uuu.sum(people,'salary')/people.length
people
不能为空)

lodash v4:


\意思是(人,'salary')

这个代码有效吗?reduce似乎没有找到avg,而是返回了所有工资的总和。除了reduce中的明显错误使其返回的是OP问题中的总和而不是平均值之外,这与他的解决方案有何不同?(真的在问,没有批评的意思)
a+m.salary/p.length
-看看
p.length
-这使结果平均,而不是总和。@lascort如果你不相信我,你可以自己试试。转到,打开控制台,创建
人员
数组,然后复制/粘贴我的解决方案。我并不是说它不起作用,我只是说,在我看来,它似乎与他做的事情相同,但顺序不同。除了他显然在reduce函数中犯了一个错误,但我认为这只是一个输入错误。但我可能弄错了,我不是洛达斯的专家,这就是我为什么这么做的原因asking@lascort问题是“使用lodash找到平均值的最有效方法”。我认为这是最“高效”和优雅的方式。我认为这比他自己的解决方案更清楚。如果有人有更好的想法,他们可以自己写答案。如果我发现他们的解决方案更好,我甚至会删除我的答案。也只适用于v4.*@Stalinko,这使它变得更短,而不是更简单,当你使用IDE时,你可以看到预算的类型(在TypeScript的情况下),或者你可以使用go to declaration,find references等。答案很好,他可以做的是使用
p=>p.budget
@Stalinko不完全是,使用arrow方法时,它省略了计算,并使用中间件方法查找“预算”成员,正如Almis所说,箭头使IDE能够查看数据类型。@FredericYesidPeñasánchez让人们决定他们更喜欢什么。无论如何,这两种方法没有太大区别。