web-dev-qa-db-ja.com

配列をcoffeescriptで並べ替えるにはどうすればよいですか?

このような配列で:

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' }
]

そして、あなたがコーヒースクリプトで姓でソートしたいなら、あなたはこれをすることができます:

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()

しかし、それは配列を適切にソートしませんでした。

複数のフィールドで並べ替える方法はありますか?つまり、最初に州で並べ替え、次に姓で並べ替えますか?上記の「sortBy」関数を改善し、少なくとも2つのフィールドで並べ替える機能を追加したいと思っていました。

21
jiy

もっと簡単な方法があります。一般化された並べ替え関数を再利用し、||を使用してそれらを連結するだけです。

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']

ただし、それぞれに順序やその他のパラメータを設定することはできなくなります。

20
Ricardo Tomasi

または、 nderscore 's sortBy の使用を検討して、自分で実装する必要がないようにすることもできます。

_(users).sortBy (u) -> [u.state, u.lname.toUpperCase()]
16
Nevir

これは、 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')

私が見つけたより一般的な例に基づいて ここ

3
daniel_fahy