如何使用coffeescript对数组进行排序?

时间:2012-03-20 23:55:40

标签: arrays sorting 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' }
]

并且您希望使用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个字段排序的能力。

3 个答案:

答案 0 :(得分: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']

但是你失去了在每个参数上设置顺序或其他参数的能力。

答案 1 :(得分:16)

或者,您可能需要考虑使用UnderscoresortBy,这样您就不必自己实现它了:

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

答案 2 :(得分: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