2014-02-17 116 views
4

計算平均值我有一個數組,像這樣:總結對象的數組,每個唯一對象名稱

var array = [ 
    { 
     name: "a", 
     value: 1 
    }, 
    { 
     name: "a", 
     value: 2 
    }, 
    { 
     name: "a", 
     value: 3 
    }, 
    { 
     name: "b", 
     value: 0 
    }, 
    { 
     name: "b", 
     value: 1 
    } 
]; 

我需要一個這樣的數組:

var newarray = [ 
    { 
     name: "a", 
     value: 2 
    }, 
    { 
     name: "b", 
     value: 0.5 
    } 
] 

凡新數組每個唯一名稱作爲具有平均值的對象。

有沒有簡單的方法來完成這個?

+0

你只是想知道'了'和'B'? –

+0

a和b只是例子。我的數組將具有比a和b更多的名稱。我的值如何不正確? a的值爲1,2和3. 1 + 2 + 3 = 6,a有3個值,所以6/3 = 2。b的值爲0和1. 0 + 1 = 1,有2個值b,所以1/2 = 0.5。 – user3317337

+0

@ user3317337:對不起,那是我的錯誤 - 我雖然第三個是「b」,而不是「a」。 –

回答

5

您必須遍歷數組,計算每個對象的總和和計數。這裏有一個快速的實現:

function average(arr) { 
    var sums = {}, counts = {}, results = [], name; 
    for (var i = 0; i < arr.length; i++) { 
     name = arr[i].name; 
     if (!(name in sums)) { 
      sums[name] = 0; 
      counts[name] = 0; 
     } 
     sums[name] += arr[i].value; 
     counts[name]++; 
    } 

    for(name in sums) { 
     results.push({ name: name, value: sums[name]/counts[name] }); 
    } 
    return results; 
} 

Demonstration

注意,這種東西可以,如果你使用像Underscore.js庫中變得容易得多:

var averages = _.chain(array) 
       .groupBy('name') 
       .map(function(g, k) { 
        return { 
         name: k, 
         value: _.chain(g) 
           .pluck('value') 
           .reduce(function(x, y) { return x + y }) 
           .value()/g.length 
        }; 
       }) 
       .value(); 

Demonstration

+0

謝謝。我很欣賞快速反應和示範。 – user3317337

+1

我不知道下劃線版本「更容易」。它需要理解*鏈*,* groupBy *,* map *,* pluck *,* value *和* reduce * plus需要一個合適的* reduce *函數。我敢打賭它也比POJS版本慢得多(可以更簡潔)。 ;-) – RobG

+0

@RobG公平點。如果你喜歡功能性編程策略,這會更容易。我主要想提供一個替代方案。 –

2
var array = [ 
    { 
     name: "a", 
     value: 1 
    }, 
    { 
     name: "a", 
     value: 2 
    }, 
    { 
     name: "a", 
     value: 3 
    }, 
    { 
     name: "b", 
     value: 0 
    }, 
    { 
     name: "b", 
     value: 1 
    } 
]; 
var sum = {}; 
for(var i = 0; i < array.length; i++) { 
    var ele = array[i]; 
    if (!sum[ele.name]) { 
     sum[ele.name] = {}; 
     sum[ele.name]["sum"] = 0; 
     sum[ele.name]["count"] = 0; 
    } 
    sum[ele.name]["sum"] += ele.value; 
    sum[ele.name]["count"]++; 
} 
var result = []; 
for (var name in sum) { 
    result.push({name: name, value: sum[name]["sum"]/sum[name]["count"]}); 
} 
console.log(result); 
0

並使用ECMA5(如我們似乎缺少一個)

var sums = {}, 
    averages = Object.keys(array.reduce(function (previous, element) { 
     if (previous.hasOwnProperty(element.name)) { 
      previous[element.name].value += element.value; 
      previous[element.name].count += 1; 
     } else { 
      previous[element.name] = { 
       value: element.value, 
       count: 1 
      }; 
     } 

     return previous; 
    }, sums)).map(function (name) { 
     return { 
      name: name, 
      average: this[name].value/this[name].count 
     }; 
    }, sums); 

jsFiddle

0

您可以Alasql庫一行代碼做到這一點:

var newArray = alasql('SELECT name, AVG([value]) AS [value] FROM ? GROUP BY name', 
         [array]); 

在這裏,我把「價值」在方括號中,因爲VALUE是SQL中的關鍵字。

嘗試this example在的jsfiddle

0

下面是一個ES2015版,採用減少

let arr = [ 
    { a: 1, b: 1 }, 
    { a: 2, b: 3 }, 
    { a: 6, b: 4 }, 
    { a: 2, b: 1 }, 
    { a: 8, b: 2 }, 
    { a: 0, b: 2 }, 
    { a: 4, b: 3 } 
] 

arr.reduce((a, b, index, self) => { 
const keys = Object.keys(a) 
let c = {} 

keys.map((key) => { 
    c[key] = a[key] + b[key] 

    if (index + 1 === self.length) { 
    c[key] = c[key]/self.length 
    } 
}) 

return c 
})