Ruby 按字符串键对哈希进行排序
假设我得到一个字符串:Ruby 按字符串键对哈希进行排序,ruby,sorting,hash,Ruby,Sorting,Hash,假设我得到一个字符串: "27,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,12,17,17,41,17,17,17,17,17,17,17,17,17,17,17,17,17,26,26,26,26,26,26,26,26,26,29,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,
"27,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,12,17,17,41,17,17,17,17,17,17,17,17,17,17,17,17,17,26,26,26,26,26,26,26,26,26,29,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,40,48,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,34,34,34,34,34,34,36,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,40,40,40,40,40,40,40,40,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,48,49,29,41,6,30,11,29,29,36,29,29,36,29,43,1,29,29,29,1,41"
我通过调用
str.split(',')
然后通过调用
arr.compact.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
我会得到一份看起来像
{"1"=>2, "6"=>1, "39"=>23, "36"=>23, "34"=>39, "32"=>31, "30"=>18, "3"=>8, "2"=>10, "28"=>36, "29"=>21, "26"=>41, "27"=>48, "49"=>1, "44"=>4, "43"=>14, "42"=>34, "48"=>2, "40"=>9, "41"=>10, "11"=>1, "17"=>15, "12"=>1}
但是,我想按键对散列进行排序
我已经尝试了列出的解决方案
我相信我的问题与键是字符串这一事实有关
我得到的最接近的是使用
Hash[h.sort_by{|k,v| k.to_i}]
您可以将arr.compact.injectHash.new0{| h,e | h[e]+=1;h}分配给变量,并按键对其排序:
num=arr.compact.injectHash.new0{| h,e | h[e]+=1;h}
num.keys.sort
这将按键对哈希进行排序。您可以将arr.compact.injectHash.new0{h,e | h[e]+=1;h}分配给一个变量,并按键对其进行排序:
num=arr.compact.injectHash.new0{| h,e | h[e]+=1;h}
num.keys.sort
这将按键对哈希进行排序。假设您从
str = "27,2,2,2,41,26,26,26,48,48,41,6,11,1,41"
并创建了以下哈希
h = str.split(',').inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
#=> {"27"=>1, "2"=>3, "41"=>3, "26"=>3, "48"=>2, "6"=>1, "11"=>1, "1"=>1}
我删除了compact,因为数组str.split',可能只包含空字符串,没有nils
在继续之前,您可能希望将最后一步更改为
h = str.split(/\s*,\s*/).each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
#=> {"27"=>1, "2"=>3, "41"=>3, "26"=>3, "48"=>2, "6"=>1, "11"=>1, "1"=>1}
正则表达式上的拆分允许在每个逗号之前或之后使用一个或多个空格,并且避免了使用那个讨厌的空格;H请注意,块变量是反向的
然后
创建一个新的散列,其中包含按键的整数表示排序的h的键值对。看
注意,我们已经创建了两个哈希。这里有一种方法可以通过修改h来实现
h.keys.sort_by(&:to_i).each { |k| h[k] = h.delete(k) }
#=> ["1", "2", "6", "11", "26", "27", "41", "48"] (each always returns the receiver)
h #=> {"1"=>1, "2"=>3, "6"=>1, "11"=>1, "26"=>3, "27"=>1, "41"=>3, "48"=>2}
最后,另一种选择是在创建哈希之前对str.split'”进行排序
str.split(',').sort_by(&:to_i).each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
#=> {"1"=>1, "2"=>3, "6"=>1, "11"=>1, "26"=>3, "27"=>1, "41"=>3, "48"=>2}
假设你是从
str = "27,2,2,2,41,26,26,26,48,48,41,6,11,1,41"
并创建了以下哈希
h = str.split(',').inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
#=> {"27"=>1, "2"=>3, "41"=>3, "26"=>3, "48"=>2, "6"=>1, "11"=>1, "1"=>1}
我删除了compact,因为数组str.split',可能只包含空字符串,没有nils
在继续之前,您可能希望将最后一步更改为
h = str.split(/\s*,\s*/).each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
#=> {"27"=>1, "2"=>3, "41"=>3, "26"=>3, "48"=>2, "6"=>1, "11"=>1, "1"=>1}
正则表达式上的拆分允许在每个逗号之前或之后使用一个或多个空格,并且避免了使用那个讨厌的空格;H请注意,块变量是反向的
然后
创建一个新的散列,其中包含按键的整数表示排序的h的键值对。看
注意,我们已经创建了两个哈希。这里有一种方法可以通过修改h来实现
h.keys.sort_by(&:to_i).each { |k| h[k] = h.delete(k) }
#=> ["1", "2", "6", "11", "26", "27", "41", "48"] (each always returns the receiver)
h #=> {"1"=>1, "2"=>3, "6"=>1, "11"=>1, "26"=>3, "27"=>1, "41"=>3, "48"=>2}
最后,另一种选择是在创建哈希之前对str.split'”进行排序
str.split(',').sort_by(&:to_i).each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
#=> {"1"=>1, "2"=>3, "6"=>1, "11"=>1, "26"=>3, "27"=>1, "41"=>3, "48"=>2}
哈希不应被视为排序数据结构。它们还有其他优点和用例,可以按顺序返回它们的值。正如Mladen Jablanović已经指出的,当您需要排序的键/值对时,元组数组可能是更好的数据结构 但是在Ruby的当前版本中,实际上存在一个特定的顺序,当您调用散列中的每一个键/值对时,返回键/值对,这就是插入的顺序。使用这种行为,您只需构建一个新的散列,并按照您希望的顺序将所有键/值对插入到该新散列中。但请记住,当您稍后添加更多条目时,顺序将中断
string = "27,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,12,17,17,41,17,17,17,17,17,17,17,17,17,17,17,17,17,26,26,26,26,26,26,26,26,26,29,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,40,48,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,34,34,34,34,34,34,36,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,40,40,40,40,40,40,40,40,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,48,49,29,41,6,30,11,29,29,36,29,29,36,29,43,1,29,29,29,1,41"
sorted_number_count_tupels = string.split(',').
group_by(&:itself).
map { |k, v| [k, v.size] }.
sort_by { |(k, v)| k.to_i }
#=> [["1",2],["2",10],["3",8],["6",1],["11",1],["12",1],["17",15],["26",41],["27",48],["28",36],["29",21],["30",18],["32",31],["34",39],["36",23],["39",23],["40",9],["41",10],["42",34],["43",14],["44",4],["48",2],["49",1]]
sorted_number_count_hash = sorted_number_count_tupels.to_h
#=> { "1" => 2, "2" => 10, "3" => 8, "6" => 1, "11" => 1, "12" => 1, "17" => 15, "26" => 41, "27" => 48, "28" => 36, "29" => 21, "30" => 18, "32" => 31, "34" => 39, "36" => 23, "39" => 23, "40" => 9, "41" => 10, "42" => 34, "43" => 14, "44" => 4, "48" => 2, "49" => 1}
哈希不应被视为排序数据结构。它们还有其他优点和用例,可以按顺序返回它们的值。正如Mladen Jablanović已经指出的,当您需要排序的键/值对时,元组数组可能是更好的数据结构 但是在Ruby的当前版本中,实际上存在一个特定的顺序,当您调用散列中的每一个键/值对时,返回键/值对,这就是插入的顺序。使用这种行为,您只需构建一个新的散列,并按照您希望的顺序将所有键/值对插入到该新散列中。但请记住,当您稍后添加更多条目时,顺序将中断
string = "27,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,12,17,17,41,17,17,17,17,17,17,17,17,17,17,17,17,17,26,26,26,26,26,26,26,26,26,29,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,40,48,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,34,34,34,34,34,34,36,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,40,40,40,40,40,40,40,40,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,48,49,29,41,6,30,11,29,29,36,29,29,36,29,43,1,29,29,29,1,41"
sorted_number_count_tupels = string.split(',').
group_by(&:itself).
map { |k, v| [k, v.size] }.
sort_by { |(k, v)| k.to_i }
#=> [["1",2],["2",10],["3",8],["6",1],["11",1],["12",1],["17",15],["26",41],["27",48],["28",36],["29",21],["30",18],["32",31],["34",39],["36",23],["39",23],["40",9],["41",10],["42",34],["43",14],["44",4],["48",2],["49",1]]
sorted_number_count_hash = sorted_number_count_tupels.to_h
#=> { "1" => 2, "2" => 10, "3" => 8, "6" => 1, "11" => 1, "12" => 1, "17" => 15, "26" => 41, "27" => 48, "28" => 36, "29" => 21, "30" => 18, "32" => 31, "34" => 39, "36" => 23, "39" => 23, "40" => 9, "41" => 10, "42" => 34, "43" => 14, "44" => 4, "48" => 2, "49" => 1}
笔记
契约
Stringsplit不能返回nil元素。在这里,紧凑型不会有用。split可能返回空字符串,但:
p "1,,2,3".split(',')
# ["1", "", "2", "3"]
p "1,,2,3".split(',').compact
# ["1", "", "2", "3"]
p "1,,2,3".split(',').reject(&:empty?)
# ["1", "2", "3"]
注射
如果必须在inject块内使用两条语句,则最好使用带有\u对象的每个\u:
arr.compact.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
可以重写:
arr.compact.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
散列还是数组?
如果需要对结果进行排序,成对数组可能比哈希更合适
字符串还是整数?
如果接受整数作为键,可能会使代码更容易编写
重构
下面是重写代码的一种可能性:
str.split(',')
.reject(&:empty?)
.map(&:to_i)
.group_by(&:itself)
.map { |k, v| [k, v.size] }
.sort
它输出:
[[1, 2], [2, 10], [3, 8], [6, 1], [11, 1], [12, 1], [17, 15], [26, 41], [27, 48], [28, 36], [29, 21], [30, 18], [32, 31], [34, 39], [36, 23], [39, 23], [40, 9], [41, 10], [42, 34], [43, 14], [44, 4], [48, 2], [49, 1]]
如果您真的想要散列,您可以添加。到:
笔记
契约
Stringsplit不能返回nil元素。在这里,紧凑型不会有用。split可能返回空字符串,但:
p "1,,2,3".split(',')
# ["1", "", "2", "3"]
p "1,,2,3".split(',').compact
# ["1", "", "2", "3"]
p "1,,2,3".split(',').reject(&:empty?)
# ["1", "2", "3"]
注射
如果必须在inject块内使用两条语句,则最好使用带有\u对象的每个\u:
arr.compact.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
可以重写:
arr.compact.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
散列还是数组?
如果需要对结果进行排序,成对数组可能比哈希更合适
字符串还是整数?
如果接受整数作为键,可能会使代码更容易编写
重构
下面是重写代码的一种可能性:
str.split(',')
.reject(&:empty?)
.map(&:to_i)
.group_by(&:itself)
.map { |k, v| [k, v.size] }
.sort
它输出:
[[1, 2], [2, 10], [3, 8], [6, 1], [11, 1], [12, 1], [17, 15], [26, 41], [27, 48], [28, 36], [29, 21], [30, 18], [32, 31], [34, 39], [36, 23], [39, 23], [40, 9], [41, 10], [42, 34], [43, 14], [44, 4], [48, 2], [49, 1]]
如果您真的想要散列,您可以添加。到:
Ruby哈希将保持添加的键的顺序。如果 e数组足够小,可以进行排序,我只需更改
str.split(',').
到
为了获得值,因此也需要对其进行哈希排序…Ruby哈希将保留添加的键的顺序。如果数组足够小,可以进行排序,我只需更改
str.split(',').
到
为了获得值,因此也需要对其进行哈希排序…严格来说,Ruby哈希是未排序的。如果需要特定的顺序,请创建一个元组数组。如果你想对它们进行数字排序,你应该在拆分后立即将它们转换成整数。这是可行的:str.split','.group_by&:itself.map{| k,v |[k,v.size]}.sort_by{| k,v | k.to |i}.to_h@MladenJablanović感谢您的洞察力,这是最好的方法,在拆分后将它们映射到整数。哈希[h.sort_by]有什么问题吗{| k,v | k.to|i}]??默认情况下,每个_with_对象返回初始化的散列,而with inject则必须通过显式返回初始化的散列;严格地说,Ruby散列是未排序的。如果需要特定的顺序,请创建一个元组数组。如果要对它们进行数字排序,则应在拆分后立即将其转换为整数。此工作而是:str.split','.group_by&:itself.map{k,v{k,v.size]}。按{k,v{k.to}排序_h@MladenJablanović感谢您的洞察力,这是最好的方法,在拆分后将它们映射到整数??默认情况下,每个带有“”对象的“”返回初始化的哈希值,而带有“”对象的“”则必须通过;h显式返回初始化的哈希值。这不起作用,因为它实际上只返回一个排序键数组。这不起作用,因为它实际上只返回一个排序键数组。