【问题标题】:Sorting a hash table of objects (by the attributes of the objects) in Ruby在 Ruby 中对对象的哈希表进行排序(按对象的属性)
【发布时间】:2012-02-01 22:23:31
【问题描述】:

假设我有一个名为 Person 的类,它包含诸如姓氏、名字、地址等内容。

我还有一个 Person 对象的哈希表,需要按姓氏和名字排序。 我知道 sort_by 不会永久更改哈希,这很好,我只需要按该顺序打印。目前,我正在尝试使用以下方法进行排序/打印:

@hash.sort_by {|a,b| a <=> b}.each { |person| puts person.last}

我已重载 运算符以按最后/第一个排序,但实际上似乎没有任何排序。 puts 只是按照哈希的原始顺序输出。我花了整整 4 天的时间来解决这个问题(这是一项学校作业,也是我的第一个 Ruby 程序)。有任何想法吗?我确信这很容易,但我很难让我的大脑摆脱 C++ 的思维方式。

【问题讨论】:

    标签: ruby sorting object hash attributes


    【解决方案1】:

    您似乎混淆了sortsort_by

    sort 将集合中的两个对象生成到块中,并希望您返回类似 的值:-1,0 或 1,具体取决于参数是否相等、升序或降序,例如

    %w(one two three four five).sort {|a,b| a.length <=> b.length}
    

    按长度对字符串进行排序。如果您想使用 运算符

    ,这是要使用的表格

    sort_by 一次从集合中生成一个对象,并希望您返回要排序的对象 - 您不应该在这里进行任何比较。 Ruby 然后在这些对象上使用 对您的集合进行排序。前面的例子可以改写为

    %w(one two three four five).sort_by {|s| s.length}
    

    这也称为schwartzian transform

    在您的情况下,集合是一个哈希,因此事情稍微复杂一些:传递到块中的值是包含键/值对的数组,因此您需要从该对中提取人员对象。您也可以只处理 @hash.keys 或 @hash.values(取决于人员对象是键还是值)

    【讨论】:

    • 学习像 Schwartzian 变换这样的东西让我成为一个快乐的人。我现在知道了,我即将上交。非常感谢您的帮助和精彩的帖子。
    【解决方案2】:

    如果您重写了 运算符以适当地对 Person 对象进行排序,那么您可以简单地执行以下操作:

    @hash.sort_by{ |key, person| person }
    

    因为 sort_by 将为块的每次迭代产生哈希键和对象(在您的情况下为人)。因此,上面的代码将根据 Person 对象对散列进行排序 - 您已经为其指定了 运算符。

    【讨论】:

      【解决方案3】:

      当你#.sort_by 带有哈希时,传递给块的参数是'key','value',而不是'element a'和'element b'。试试:

      @hash.sort_by{|key,value| value.last}.each{|key,value| puts value.last}
      

      另外,请参阅 Frederick Cheung 对 #sort#sort_by 的出色解释。

      【讨论】:

        猜你喜欢
        • 2010-10-27
        • 2011-03-21
        • 2023-03-27
        • 1970-01-01
        • 2016-02-08
        • 2018-07-02
        • 2011-07-07
        • 2015-09-10
        相关资源
        最近更新 更多