Kyl*_*rtz 2 ruby sorting hash key-value alphabetical
初学者在这里.我的第一个问题.放轻松我.
给出以下哈希:
pets_ages = {"Eric" => 6, "Harry" => 3, "Georgie" => 12, "Bogart" => 4, "Poly" => 4,
"Annie" => 1, "Dot" => 3}
Run Code Online (Sandbox Code Playgroud)
并运行以下方法:
pets_ages.sort {|x, y| x[1] <=> y[1]}.to_h
Run Code Online (Sandbox Code Playgroud)
返回以下内容:
{
"Annie" => 1,
"Dot" => 3,
"Harry" => 3,
"Poly" => 4,
"Bogart" => 4,
"Eric" => 6,
"Georgie" => 12
}
Run Code Online (Sandbox Code Playgroud)
您会注意到散列很好地按照预期的值排序.我想改变的是键的排序,以便在打平时保持字母顺序.注意"Dot"和"Harry"在这方面是正确的,但由于某种原因,"Poly"和"Bogart"不是.我的理论是,它在绑定的情况下按长度自动排序键,而不是按字母顺序排序.我怎么能改变呢?
在许多语言中,Hashes/Dicts不是订购的,因为它们是如何在封面下实现的.Ruby 1.9+非常适合保证订购.
您可以在一次通过中执行此操作 - Ruby允许您按任意条件进行排序.
# Given
pets_ages = {"Eric" => 6, "Harry" => 3, "Georgie" => 12, "Bogart" => 4, "Poly" => 4, "Annie" => 1, "Dot" => 3}
# Sort pets by the critera of "If names are equal, sort by name, else, sort by age"
pets_ages.sort {|(n1, a1), (n2, a2)| a1 == a2 ? n1 <=> n2 : a1 <=> a2 }.to_h
# => {"Annie"=>1, "Dot"=>3, "Harry"=>3, "Bogart"=>4, "Poly"=>4, "Eric"=>6, "Georgie"=>12}
Run Code Online (Sandbox Code Playgroud)
散列#sort将返回一[k, v]对数组,但这些k, v对可以按照您想要的单个过程中的任何条件进行排序.一旦我们有了排序对,我们就把它变回Hash with Array#to_h(Ruby 2.1+),或者你可以Hash[sorted_result]在早期版本中使用,如Beartech指出的那样.
您可以在排序块中获得所需的复杂内容; 如果您熟悉Javascript排序,Ruby实际上在这里工作相同.该<=>方法返回-1,0或1,具体取决于对象如何相互比较.#sort只是期望其中一个返回值,它告诉它两个给定值如何相互关联.你甚至不必用<=>在所有的,如果你不想-这样的事情是等同于更紧凑的形式:
pets_ages.sort do |a, b|
if a[1] == b[1]
if a[0] > b[0]
1
elsif a[0] < b[0]
-1
else
0
end
else
if a[1] > b[1]
1
elsif a[1] < b[1]
-1
end
end
end
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,只要你总是在集合中返回一些东西(-1 0 1),你的排序函数可以做你想做的任何事情,所以你可以根据自己的喜好编写它们.但是,由于超级方便的<=>运算符,在Ruby中几乎不需要这种冗长的形式!
正如Stefan指出的那样,你有一个很大的捷径:Array#<=>足以比较比较数组之间的每个条目.这意味着我们可以做以下事情:
pets_ages.sort {|a, b| a.reverse <=> b.reverse }.to_h
Run Code Online (Sandbox Code Playgroud)
这需要每个[k,v]对,将其反转为[v,k],并使用Array#<=>进行比较.由于您需要在每个[k,v]对上执行相同的操作,因此您可以使用#sort_by进一步缩短它
pets_ages.sort_by {|k, v| [v, k] }.to_h
Run Code Online (Sandbox Code Playgroud)
这样做对于每个散列条目,它将键和值传递给块,并且块的返回结果用于将该[k,v]对与其他条目进行比较.由于将[v,k]与另一个[v,k]对比较给出了我们想要的结果,我们只返回一个由[v,k]组成的数组,sort_by通过以下方式收集和排序原始的[k,v]对. .