2012-03-20 67 views
19

有一個這樣的數組:如何使用coffeescript對Array進行排序?

users = [ 
    { id: 1, fname: 'Fred', lname: 'Flinstone', state: 'CA' }, 
    { id: 2, fname: 'George', lname: 'Winston', state: 'FL' }, 
    { id: 3, fname: 'Luke', lname: 'Skywalker', state: 'CA' } 
] 

,你想用的CoffeeScript姓氏排序,你可以這樣做:

users.sort (a,b) -> 
    return if a.lname.toUpperCase() >= b.lname.toUpperCase() then 1 else -1 

我使用這樣的功能的嘗試:

sortBy = (field, reverse, primer) -> 
    key = (x) -> 
     return if primer? then primer x[field] else x[field] 
    return (a,b) -> 
     A = key a 
     B = key b 
     return (A < B ? -1 : (A > B ? 1 : 0)) * [1,-1][+!!reverse] 

它被這樣調用:

users.sort sortBy "lname", false, (a) -> 
    return a.toUpperCase() 

但這並沒有正確排序數組。

有沒有辦法按1個以上的字段進行排序,即按州排序,然後按姓氏排序?我希望能夠改進上面的「sortBy」功能,並添加至少2個字段的排序功能。

+2

什麼樣的事情可能比「更好」? (其實我會用'<='而不是'<'來幫助保持排序穩定。) – Pointy 2012-03-20 23:59:14

+3

這不是JSON。 – 2012-03-20 23:59:56

+0

你可以在那裏使用三元運算符:'返回a.lname.toUpperCase()> b.lname.toUpperCase()? 1:-1' – 2012-03-21 00:00:26

回答

20

有一個簡單的方法。剛剛重新使用廣義分類功能,並使用||將它們連接起來:

sortBy = (key, a, b, r) -> 
    r = if r then 1 else -1 
    return -1*r if a[key] > b[key] 
    return +1*r if a[key] < b[key] 
    return 0 

users.sort (a,b) -> 
    sortBy('id', a, b, true) or 
    sortBy('lname', a, b) or 
    sortBy('fname', a, b) 

功能很便宜。然後,您可以建立一個抽象爲:

sortByMultiple = (a, b, keys) -> 
    return r if (r = sortBy key, a, b) for key in keys 
    return 0 

users.sort (a,b) -> sortByMultiple a, b, ['id', 'lname', 'fname'] 

但你失去了設置命令或其他參數對他們每個人的能力。

+0

這真的很漂亮。我試圖理解'or'是如何與鏈接函數一起工作的。是否因爲它只在前一個返回'0'時才移動到下一個sortyBy函數?或者換句話說,它會繼續排序直到第一個鍵被滿足(即'0'),然後移動到下一個鍵? – jiy 2012-03-21 03:20:56

+0

經過測試將sortBy函數與or鏈接起來非常棒!將sortByMultiple投入混合並不成功,但沒有任何內容正確排序。感謝您提供非常有用的答案! – jiy 2012-03-21 12:56:35

+0

@jiy是的,就是這麼多。繼續下去,直到其中一個條件返回非零值。 – 2012-03-21 20:20:19

15

或者,你可能要考慮使用UnderscoresortBy,這樣你就不必自己實現它:

_(users).sortBy (u) -> [u.state, u.lname.toUpperCase()] 
+0

謝謝!這看起來非常有前途。正是我在找的 – jiy 2012-03-21 01:30:29

+0

你的答案中的鏈接不再存在http://underscorejs.org/和http://underscorejs.org/#sortBy是新鏈接 – 2017-11-20 10:12:43

3

這是我認爲在使用lodash時默認實現的,但事實並非如此。

所以我們來了!

sortByLowercase: (collection, key) -> 
    collection.sort (a, b) -> 
     [av, bv] = [a[key], b[key]] 
     [av, bv] = [av.toLowerCase(), bv.toLowerCase()] 
     if av >= bv then 1 else if av <= bv then -1 else 0 

sortByLowercase(users,'lname') 

基於一個更通用的例子,我發現here

相關問題