我有一个对象数组,对象的数量是可变的 -
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 });
但我不确定这是否是正确的做法。
答案 0 :(得分:29)
为什么所有人都在这里变得过于复杂?
const people = [
{name: 'Alejandro', budget: 56},
{name: 'Juan', budget: 86},
{name: 'Pedro', budget: 99}];
let average = _.meanBy(people, (p) => p.budget);
答案 1 :(得分:20)
"高效"是一个非常模糊的术语。说"高效"您可以考虑性能,可读性或简洁等。我认为最可读和简明解决方案是:
_(people).filter({ job: 'manager'}).filter('salary').reduce(function(a,m,i,p) {
return a + m.salary/p.length;
},0);
最 fast 解决方案是不使用loadash,也不使用任何库,也不使用任何filter
,reduce
方法。请改用for
循环:
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;
我认为在大多数情况下,客户端开发可读性比性能更重要,所以我认为第一个变体是最有效的&#34;。
答案 2 :(得分:3)
我不知道lowdash,但也许一个普通的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
这会将对象传递给 reduce ,因为 accumulator 具有三个属性:工资总和,工资计数和目前的平均值。它迭代所有对象,对工资求和,计算有多少,并计算每次迭代的平均值。最终它返回该对象(累加器)并读取 average 属性。
调用单个内置方法应该比调用4个本机函数更快(即更高效)。 “优雅”是旁观者的眼睛。 ; - )
顺便说一下,对象文字中有错误,应该是:var people = [{
name: 'john',
job: 'manager',
salary: 2000
},
{
name: 'sam',
job: 'manager',
salary: 6000
},
{
name: 'frodo',
job: 'janitor'
}];
答案 3 :(得分:3)
lodash v3:
_.sum(people, 'salary') / people.length
(people
必须为空)
lodash v4:
_.meanBy(people, 'salary')
答案 4 :(得分:1)
function average(acc, ele, index) {
return (acc + ele) / (index + 1);
}
var result = _.chain(people)
.filter('job', 'manager')
.map('salary')
.reduce( average )
.value();
答案 5 :(得分:1)
使用功能更强大的lodash
版本(lodash-fp
)和es2015
,您可以使用箭头功能和自动咖喱来获得更灵活,更实用的解决方案。
你可以把它放在一个丑陋的衬里:
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);
答案 6 :(得分:0)
我能想到的最干净(优雅)的方式是:
var salariesOfManagers = _(people).filter({job: 'manager'}).filter('salary').pluck('salary');
var averageSalary = salariesOfManagers.sum() / salariesOfManagers.value().length;
它需要项目的总和并将其与项目数量相除,这几乎是平均值的定义。
太糟糕了,如果你想让它整齐一行,代码就会变得不那么清晰了。
答案 7 :(得分:0)
使用lodash/fp和ES2016 / ES6可以更实用的方式完成
@ IN NS ns1.blublublu.com. //Saying there is a nameserver at ns1.blublublu.com
@ IN NS ns2.blublublu.com.
@ IN A 192.168.100.13 //static if of the domain blublublu.com
@ IN AAAA ::1
ns1 IN A 192.168.100.13 //subdomain of ns1.blublublu.com
ns2 IN A 192.168.100.14 //subdomain of ns2.blublublu.com, if is the same computer (not ideal) then it would be the same ip
你做的是什么 1.获取所有对象&#39;经理&#39;类型 2.提取工资&#39;他们的财产/领域 3.使用均值函数求平均值
以下是为方便起见的完整版代码,可在nodejs上运行。
const avg = flow(
filter({job: 'manager'}),
map('salary'),
mean
)
console.log(avg(people))