【问题标题】:How do I sort an Array with coffeescript?如何使用咖啡脚本对数组进行排序?
【发布时间】:2012-04-05 12:11:44
【问题描述】:

使用这样的数组:

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

但这并没有正确地对数组进行排序。

有没有办法按多个字段排序,即先按州排序,然后按姓氏?我希望改进上面的“sortBy”功能,并添加至少按 2 个字段排序的功能。

【问题讨论】:

  • 还有什么比这“更好”的呢? (实际上我会使用&lt;= 而不是&lt; 来帮助保持排序稳定。)
  • 你可以在那里使用三元运算符:return a.lname.toUpperCase() &gt; b.lname.toUpperCase() ? 1 : -1
  • “更好”和“失败”是什么意思?
  • @LightnessRacesinOrbit:条件运算符是 C-ish 语言家族中唯一的三元运算符,包括 JavaScript、AFAICT。因此,术语“三元运算符”长期以来一直被认为是“条件运算符”的同义词。 “条件”是可取的,但“三元”是完全有效的。
  • @LightnessRacesinOrbit:以“ahem”开头的句子带有强烈的含义,即“你说的是错误的”。你可能没有说过,但你肯定暗示过。

标签: arrays sorting coffeescript


【解决方案1】:

有一个更简单的方法。只需重新使用您的广义排序函数,并使用|| 连接它们:

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',它只会移动到下一个 sortyBy 函数?或者另一种说法是它会继续排序直到第一个键被满足(即'0')然后移动到下一个?
  • 已测试用 or 链接 sortBy 函数 - 效果很好!将 sortByMultiple 加入混合中并不成功,但是没有正确排序。感谢您提供非常有帮助的答案!
  • @jiy 是的,差不多就是这样。继续,直到其中一个条件返回非零值。
  • 修正了sortByMultiple 的代码,我忘了传递参数。
【解决方案2】:

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

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

【讨论】:

【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 2012-08-26
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多