[英]Using Lodash or vanilla JS what is the most efficient way to filter an array based on object keys?
[英]most efficient way to find average using lodash
我有一個對象數組,對象的數量是可變的 -
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 });
但我不確定這是否是正確的方法。
為什么所有人都在這里變得過於復雜?
const people = [ { name: 'Alejandro', budget: 56 }, { name: 'Juan', budget: 86 }, { name: 'Pedro', budget: 99 }, ]; const average = _.meanBy(people, (p) => p.budget); console.log(average);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
根據文檔: https : //lodash.com/docs/#meanBy
“高效”是一個非常含糊的詞。 說“高效”,您可以考慮性能、可讀性或簡潔性等。 我認為最易讀和簡潔的解決方案是:
_(people).filter({ job: 'manager'}).filter('salary').reduce(function(a,m,i,p) {
return a + m.salary/p.length;
},0);
最快速的解決方案是根本不使用 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;
我認為對於客戶端開發而言,在大多數情況下可讀性比性能更重要,所以我認為第一個變體是最“有效”的。
lodash v3:
_.sum(people, 'salary') / people.length
( people
不能為空)
lodash v4:
_.meanBy(people, 'salary')
我不知道 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
此傳遞一個目的是減少作為具有三個屬性累加器:薪金的總和,薪水的計數,和到目前為止的平均值。 它迭代所有對象,匯總工資,計算有多少,並計算每次迭代的平均值。 最終它返回該對象(累加器)並讀取平均屬性。
調用單個內置方法應該比調用 4 個本機函數更快(即更有效)。 “優雅”在旁觀者的眼中。 ;-)
順便說一句,對象文字中有錯誤,應該是:
var people = [{
name: 'john',
job: 'manager',
salary: 2000
},
{
name: 'sam',
job: 'manager',
salary: 6000
},
{
name: 'frodo',
job: 'janitor'
}];
function average(acc, ele, index) {
return (acc + ele) / (index + 1);
}
var result = _.chain(people)
.filter('job', 'manager')
.map('salary')
.reduce( average )
.value();
使用功能更強大的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);
我能想到的最干凈(優雅)的方式是:
var salariesOfManagers = _(people).filter({job: 'manager'}).filter('salary').pluck('salary');
var averageSalary = salariesOfManagers.sum() / salariesOfManagers.value().length;
它取項目的總和並將其除以項目的數量,這幾乎是平均值的定義。
太糟糕了,如果你想把它變成整潔的單行代碼,代碼會變得不太清晰。
使用lodash/fp和 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))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.