如何按键按字母顺序对Ruby Hash进行排序

时间:2021-08-09 15:58:35

I am trying to sort a Hash alphabetically by key, but I can't seem to find a way to do it without creating my own Sorting class. I found the code below to sort by value if it's an integer and I am trying to modify it but not having any luck.

我试图按键按字母顺序排序哈希,但我似乎无法找到一种方法来创建自己的排序类。我发现下面的代码按值排序,如果它是一个整数,我试图修改它,但没有任何运气。

temp["ninjas"]=36
temp["pirates"]=12
temp["cheese"]=222
temp.sort_by { |key, val| key }

My goal is to order the Hash by key then output the values. I will have to do this multiple times with different hash orders but the same values.

我的目标是按键排序Hash然后输出值。我将不得不使用不同的哈希顺序多次执行此操作,但值相同。

4 个解决方案

#1


22  

Assuming you want the output to be a hash which will iterate through keys in sorted order, then you are nearly there. Hash#sort_by returns an Array of Arrays, and the inner arrays are all two elements.

假设您希望输出是一个散列,它将按排序顺序迭代键,那么您就在那里。 Hash#sort_by返回一个数组数组,内部数组都是两个元素。

Ruby's Hash has a constructor that can consume this output.

Ruby的Hash有一个可以使用此输出的构造函数。

Try this:

尝试这个:

temp = Hash[ temp.sort_by { |key, val| key } ]

If your hash has mixed key types, this will not work (Ruby will not automatically sort between Strings and Symbols for instance) and you will get an error message like comparison of Symbol with String failed (ArgumentError). If so, you could alter the above to

如果您的散列具有混合键类型,则这将不起作用(例如,Ruby不会自动在字符串和符号之间进行排序),并且您将收到错误消息,例如Symbol与String的比较失败(ArgumentError)。如果是这样,你可以改变上面的

temp = Hash[ temp.sort_by { |key, val| key.to_s } ] 

to work around the issue. However be warned that the keys will still retain their original types which could cause problems with assumptions in later code. Also, most built-in classes support a .to_s method, so you may get unwanted results from that (such as unexpected sort order for numeric keys, or other unexpected types).

解决这个问题。但是请注意,密钥仍将保留其原始类型,这可能会导致后续代码中的假设出现问题。此外,大多数内置类都支持.to_s方法,因此您可能会从中获得不需要的结果(例如数字键或其他意外类型的意外排序顺序)。

You could, in addition, convert the keys to Strings with something like this:

此外,您可以使用以下内容将键转换为字符串:

temp = Hash[ temp.map { |key, val| [key.to_s, val] }.sort ] 

. . . although this approach would lose information about the type of the original key making it impossible to refer back to the original data reliably.

。 。 。虽然这种方法会丢失有关原始密钥类型的信息,但却无法可靠地返回原始数据。

#2


6  

sorted_by_key = Hash[original_hash.sort]

will create a new Hash by inserting the key/values of original_hash alphabetically by key. Ruby 2.x hashes remember their insertion order, so this new hash will appear sorted by key if you enumerate it or output it.

将通过按键按字母顺序插入original_hash的键/值来创建新的哈希值。 Ruby 2.x哈希记住它们的插入顺序,因此如果你枚举它或输出它,这个新哈希将按键排序。

If you insert more elements in a non-alphabetical order, this won't hold of course.

如果以非字母顺序插入更多元素,则当然不会这样。

Also, this assumes the original hash keys are all sortable/comparable.

此外,这假设原始哈希键都是可排序/可比较的。

#3


4  

Ruby's Hash remembers its insertion order now days, but earlier Rubies < v1.9 don't. But, don't bother sorting a hash as there is no advantage to doing so because basically a Hash is a random-access structure. That means the elements are all accessible at any time and it won't make a difference whether one is first or last, you can access it just the same.

Ruby的Hash现在记得它的插入顺序,但早期的Rubies 没有。但是,不要理会对哈希进行排序,因为这样做没有任何优势,因为基本上哈希是一种随机访问结构。这意味着元素都可以随时访问,无论是第一个还是最后一个都没有区别,你可以访问它们。

That's unlike an Array which acts like a sequential/text file or a chain or a queue and you have to access it linearly by iterating over it, which, at that point, the order of the elements makes a big difference.

这与一个像顺序/文本文件或链或队列一样的数组不同,你必须通过遍历它来线性访问它,在那时,元素的顺序会产生很大的不同。

So, with a Hash, get the keys, sort them, and either iterate over the list of keys or use values_at to retrieve all the values at once. For instance:

因此,使用Hash,获取密钥,对它们进行排序,然后迭代密钥列表或使用values_at一次检索所有值。例如:

hash = {
    'z' => 9,
    'a' => 1
}

sorted_keys = hash.keys.sort # => ["a", "z"]
sorted_keys.each do |k|
  puts hash[k]
end
# >> 1
# >> 9

hash.values_at(*sorted_keys) # => [1, 9]

Some languages won't even let you sort the hash, and accessing it via a sorted list of keys is the only way to extract the elements in an order, so it's probably a good idea to not get in the habit of relying on order of the key/value pairs, and instead rely on the keys.

有些语言甚至不会让你对哈希进行排序,并且通过排序的键列表访问它是提取顺序中元素的唯一方法,所以不要养成依赖于顺序的习惯。键/值对,而是依赖于键。

#4


0  

You can create a new empty hash to hold the sorted hash data. Iterate through the returned array and load the data into the new hash to hold the sorted hash data.

您可以创建一个新的空哈希来保存已排序的哈希数据。迭代返回的数组并将数据加载到新哈希中以保存已排序的哈希数据。

temp = {}
temp["ninjas"]=36
temp["pirates"]=12
temp["cheese"]=222 
temp = temp.sort_by { |key, val| key }

temp_sorted = {}
temp.each { |sub_arr| temp_sorted[sub_arr[0]] = sub_arr[1] } 
temp = temp_sorted

temp now equals {"cheese"=>222, "ninjas"=>36, "pirates"=>12}

temp现在等于{“cheese”=> 222,“ninjas”=> 36,“pirates”=> 12}

#1


22  

Assuming you want the output to be a hash which will iterate through keys in sorted order, then you are nearly there. Hash#sort_by returns an Array of Arrays, and the inner arrays are all two elements.

假设您希望输出是一个散列,它将按排序顺序迭代键,那么您就在那里。 Hash#sort_by返回一个数组数组,内部数组都是两个元素。

Ruby's Hash has a constructor that can consume this output.

Ruby的Hash有一个可以使用此输出的构造函数。

Try this:

尝试这个:

temp = Hash[ temp.sort_by { |key, val| key } ]

If your hash has mixed key types, this will not work (Ruby will not automatically sort between Strings and Symbols for instance) and you will get an error message like comparison of Symbol with String failed (ArgumentError). If so, you could alter the above to

如果您的散列具有混合键类型,则这将不起作用(例如,Ruby不会自动在字符串和符号之间进行排序),并且您将收到错误消息,例如Symbol与String的比较失败(ArgumentError)。如果是这样,你可以改变上面的

temp = Hash[ temp.sort_by { |key, val| key.to_s } ] 

to work around the issue. However be warned that the keys will still retain their original types which could cause problems with assumptions in later code. Also, most built-in classes support a .to_s method, so you may get unwanted results from that (such as unexpected sort order for numeric keys, or other unexpected types).

解决这个问题。但是请注意,密钥仍将保留其原始类型,这可能会导致后续代码中的假设出现问题。此外,大多数内置类都支持.to_s方法,因此您可能会从中获得不需要的结果(例如数字键或其他意外类型的意外排序顺序)。

You could, in addition, convert the keys to Strings with something like this:

此外,您可以使用以下内容将键转换为字符串:

temp = Hash[ temp.map { |key, val| [key.to_s, val] }.sort ] 

. . . although this approach would lose information about the type of the original key making it impossible to refer back to the original data reliably.

。 。 。虽然这种方法会丢失有关原始密钥类型的信息,但却无法可靠地返回原始数据。

#2


6  

sorted_by_key = Hash[original_hash.sort]

will create a new Hash by inserting the key/values of original_hash alphabetically by key. Ruby 2.x hashes remember their insertion order, so this new hash will appear sorted by key if you enumerate it or output it.

将通过按键按字母顺序插入original_hash的键/值来创建新的哈希值。 Ruby 2.x哈希记住它们的插入顺序,因此如果你枚举它或输出它,这个新哈希将按键排序。

If you insert more elements in a non-alphabetical order, this won't hold of course.

如果以非字母顺序插入更多元素,则当然不会这样。

Also, this assumes the original hash keys are all sortable/comparable.

此外,这假设原始哈希键都是可排序/可比较的。

#3


4  

Ruby's Hash remembers its insertion order now days, but earlier Rubies < v1.9 don't. But, don't bother sorting a hash as there is no advantage to doing so because basically a Hash is a random-access structure. That means the elements are all accessible at any time and it won't make a difference whether one is first or last, you can access it just the same.

Ruby的Hash现在记得它的插入顺序,但早期的Rubies 没有。但是,不要理会对哈希进行排序,因为这样做没有任何优势,因为基本上哈希是一种随机访问结构。这意味着元素都可以随时访问,无论是第一个还是最后一个都没有区别,你可以访问它们。

That's unlike an Array which acts like a sequential/text file or a chain or a queue and you have to access it linearly by iterating over it, which, at that point, the order of the elements makes a big difference.

这与一个像顺序/文本文件或链或队列一样的数组不同,你必须通过遍历它来线性访问它,在那时,元素的顺序会产生很大的不同。

So, with a Hash, get the keys, sort them, and either iterate over the list of keys or use values_at to retrieve all the values at once. For instance:

因此,使用Hash,获取密钥,对它们进行排序,然后迭代密钥列表或使用values_at一次检索所有值。例如:

hash = {
    'z' => 9,
    'a' => 1
}

sorted_keys = hash.keys.sort # => ["a", "z"]
sorted_keys.each do |k|
  puts hash[k]
end
# >> 1
# >> 9

hash.values_at(*sorted_keys) # => [1, 9]

Some languages won't even let you sort the hash, and accessing it via a sorted list of keys is the only way to extract the elements in an order, so it's probably a good idea to not get in the habit of relying on order of the key/value pairs, and instead rely on the keys.

有些语言甚至不会让你对哈希进行排序,并且通过排序的键列表访问它是提取顺序中元素的唯一方法,所以不要养成依赖于顺序的习惯。键/值对,而是依赖于键。

#4


0  

You can create a new empty hash to hold the sorted hash data. Iterate through the returned array and load the data into the new hash to hold the sorted hash data.

您可以创建一个新的空哈希来保存已排序的哈希数据。迭代返回的数组并将数据加载到新哈希中以保存已排序的哈希数据。

temp = {}
temp["ninjas"]=36
temp["pirates"]=12
temp["cheese"]=222 
temp = temp.sort_by { |key, val| key }

temp_sorted = {}
temp.each { |sub_arr| temp_sorted[sub_arr[0]] = sub_arr[1] } 
temp = temp_sorted

temp now equals {"cheese"=>222, "ninjas"=>36, "pirates"=>12}

temp现在等于{“cheese”=> 222,“ninjas”=> 36,“pirates”=> 12}