簡體   English   中英

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

[英]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,也不使用任何庫,也不使用任何filterreduce方法。 改用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM