2013-09-29 67 views
15

我有一個這樣的數組:計數和排序按次數

var items = [ 
    {name: 'popcorn', category: 'snacks'}, 
    {name: 'nachos', category: 'snacks'}, 
    ... 
    {name: 'coke', category: 'drinks'} 
]; 

我想通過它的項目的數量排序的類別列表(大多數項目第一):

['snacks', 'drinks'] 

這是我如何做的:

var categories = _.chain(items) 
    .countBy(function (i) { return i.category }) 
    .pairs() 
    .sortBy(function (c) { return -c[1] }) 
    .map(function (c) { return c[0] }) 
    .value(); 

所以countBy結果是一個對象,我必須使用pairs將其轉換爲數組的數組以便對其進行排序。

我不知道是否有更直接的方法來做到這一點?內置功能?

+0

你可以只通過「類」到countBy功能。使它更加富有表現力。 –

+0

返回的值看起來不像[['snacks',10] ['drinks',9]]? – JSager

+0

@JSager oops我忘了地圖的一步。固定。 –

回答

22

我不知道是否有內置函數?

不,你的方法很好。

更直接的做法嗎?

你可以通過傳遞唯一屬性的名稱,而不是功能有點縮短:

var categories = _.chain(items) 
    .countBy("category") 
    .pairs() 
    .sortBy(1).reverse() 
    .pluck(0) 
    .value(); 
+0

您可以通過按降序直接排序來保存一個步驟,而不是按升序順序排序,然後反轉(同時具有保持具有相同計數的項目順序的優勢) 'var categories = _.chain(items)。 countBy(「category」)。pairs()。sortBy(function(pair){return -pair [1];})。pluck(0).value();' (對不起,格式化代碼塊) –

+0

是的,當然你可以(和OP已經做到了這一點),但我的觀點是不使用任何回調函數(僅用於縮短代碼)。 – Bergi

1

我覺得這很不錯。你可以將它塞進一步縮小,但這會比你現在的代碼更復雜。如果你打算重複使用這些,你可以使用組合和部分來減少你寫的代碼總量。此外,請檢查lodash作爲下劃線的替代方法 - 它有更多的果汁。