在 Ruby 中对对象的哈希表进行排序(按对象的属性)
假设我有一个名为 Person 的类,它包含姓氏、名字、地址等内容。
我还有一个 Person 对象的哈希表,需要按姓氏和名字排序。 我知道 sort_by 不会永久更改哈希值,这很好,我只需要按该顺序打印。目前,我正在尝试使用以下方法就地排序/打印:
@hash.sort_by {|a,b| a <=> b}.each { |person| puts person.last}
我已经超载了 <=>;运算符按最后/第一个排序,但似乎没有任何实际排序。那里的 put 只是按照哈希的原始顺序输出。我花了 4 天时间试图解决这个问题(这是一项学校作业,也是我的第一个 Ruby 程序)。有什么想法吗?我确信这很容易,但我很难让我的大脑摆脱 C++ 的思维方式。
Say I have a class called Person, and it contains things such as last name, first name, address, etc.
I also have a hash table of Person objects that needs to be sorted by last and first name.
I understand that a sort_by will not change the hash permanently, which is fine, I only need to print in that order. Currently, I am trying to sort/print in place using:
@hash.sort_by {|a,b| a <=> b}.each { |person| puts person.last}
I have overloaded the <=> operator to sort by last/first, but nothing appears to actually sort. The puts there simply outputs in the hash's original order. I have spent a good 4 days trying to figure this out (it is a school assignment, and my first Ruby program). Any ideas? I am sure this is easy, but I am having the hardest time bringing my brain out of the C++ way of thinking.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您似乎混淆了
sort
和sort_by
sort
从集合到块生成两个对象,并期望您返回一个 <=>; like value: -1,0 或 1,具体取决于参数是否相等、升序或降序,例如按长度对字符串进行排序。如果您想使用 <=> ,则可以使用此表格。运算符
sort_by
一次从集合中生成一个对象,并期望您返回想要排序的对象 - 您不应该在此处进行任何比较。然后 Ruby 使用 <=>;在这些物品上对您的收藏进行排序。前面的示例可以重写为这也称为 schwartzian 变换
在您的情况下, collection 是一个哈希,所以事情稍微复杂一些:传递到块中的值是包含键/值对的数组,因此您需要从该对中提取 person 对象。您也可以只处理 @hash.keys 或 @hash.values (取决于 person 对象是键还是值)
You appear to be confusing
sort
andsort_by
sort
yields two objects from the collection to the block and expects you to return a <=> like value: -1,0 or 1 depending on whether the arguments are equal, ascending or descending, for exampleSorts the strings by length. This is the form to use if you want to use your <=> operator
sort_by
yields one object from the collection at a time and expects you to return what you want to sort by - you shouldn't be doing any comparison here. Ruby then uses <=> on these objecfs to sort your collection. The previous example can e rewritten asThis is also known as a schwartzian transform
In your case the collection is a hash so things are slightly more complicated: the values that are passed into the block are arrays that contain key/value pairs, so you'll need to extract the person object from that pair. You could also just work on @hash.keys or @hash.values (depending on whether the person objects are keys or values)
如果您覆盖了 <=>;运算符对 Person 对象进行适当的排序,那么您可以简单地执行以下操作:
因为 sort_by 将为块的每次迭代生成哈希键和对象(在您的情况下是一个人)。因此,上面的代码将根据 Person 对象对散列进行排序 - 您已经为其指定了 <=>操作员。
If you've overidden the <=> operator to sort Person objects appropriately then you can simply do:
because sort_by will yield both the hash key, and the object (in your case a person) to each iteration of the block. So the code above will sort your hash based on Person objects - for which you've already specified an <=> operator.
当您使用哈希
#.sort_by
时,传递给块的参数是“key”、“value”,而不是“element a”和“element b”。尝试:另外,请参阅 Frederick Cheung 对
#sort
与#sort_by
的精彩解释。When you
#.sort_by
with a Hash, the parameters passed to the block are 'key','value', not 'element a' and 'element b'. Try:Also, see Frederick Cheung's excellent explanation of
#sort
vs#sort_by
.