【问题标题】:Sort Array of Arrays by length with tiebreaker使用 tiebreaker 按长度对数组进行排序
【发布时间】:2013-08-18 08:23:30
【问题描述】:

我有一个ArrayArrays,我想按最长到最短排序。我用sort_by 很容易地做到了这一点

> a =  [ [1, 2, 9],
         [4, 5, 6, 7],
         [1, 2, 3] ]
> a.sort_by(&:length).reverse # or a.sort_by {|e| e.length}.reverse
=> [[4, 5, 6, 7], [1, 2, 3], [1, 2, 9]]

然而,我想要的是为等长的列表设置一种平局。如果两个列表的长度相等,则最后一个条目更大的列表应该排在第一位。所以在上面,[1, 2, 9][1, 2, 3]应该互换。

我不关心两个列表的长度和最后一个元素都相等的情况,如果发生这种情况,它们可以按任何顺序排列。我不知道是否/如何通过 ruby​​ 内置排序来实现这一点。

【问题讨论】:

标签: ruby arrays sorting


【解决方案1】:

你去吧:

a =  [ [1, 2, 9],[4, 5, 6, 7],[1, 2, 3] ]
a.sort { |a, b| (b.count <=> a.count) == 0 ? (b.last <=> a.last): (b.count <=> a.count)  } 

这应该给你:

[[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]

这是如何工作的:我们将一个块传递给排序函数,它首先检查数组长度是否相同,否则继续检查最后一个元素。

【讨论】:

  • 我认为(a.length == b.length) 的第一个条件更符合您的解释if the array length is same
  • 我的建议是:(a.length == b.length) ? 而不是 (b.count &lt;=&gt; a.count) == 0 ?
【解决方案2】:

您仍然可以使用sort_by 执行此操作,您只需要意识到Ruby arrays compare element-by-element

ary other_ary → -1、0、+1 或 nil

[...]

比较每个数组中的每个对象(使用 运算符)。

数组以“元素方式”的方式进行比较;前两个不相等的元素将决定整个比较的返回值。

这意味着你可以使用数组作为sort_by 键,然后输入一点整数否定来反转排序顺序,你会得到:

a.sort_by { |e| [-e.length, -e.last] }

这将为您提供您正在寻找的[[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]

如果您没有使用数字,因此“否定颠倒顺序”的技巧将不起作用,那么请使用 Shaunak's sort 方法。

【讨论】:

  • 优秀的答案,虽然对于流利的 Ruby 专家来说可能看起来很普通。
  • @BorisStitnicky:谢谢。我实际上认为这是一个受 SQL 启发的解决方案,这几乎是order by length desc, last desc 的直接音译(除了 SQL 版本同样适用于字符串,因为它不依赖于“否定反转顺序”技巧)。跨度>
  • 优秀的答案@muistooshort。出于好奇,您的解决方案与我的解决方案相比是否存在计算差异?特别是如果数组太大太复杂?我不确定 sory_by 如何执行它的块,它会排序两次还是像我的解决方案一样,它只是在同一时间修改比较。
  • @Shaunak: sort_by 执行 Schwartzian Transform 因此该块将在每个数组元素中执行一次。对于小型阵列,差异不值得担心。对于大型数组,您需要权衡块计算的开销与记忆的内存开销。
  • 谢谢!这有帮助。使用红宝石糖的缺点是我们往往会忽略这些事情。
【解决方案3】:

你可以使用

a.sort_by {|i| [i.length, i.last] }.reverse
# => [[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 2010-10-24
    • 2021-04-23
    • 2021-11-09
    • 1970-01-01
    相关资源
    最近更新 更多