如何根据 Ruby 中的出现频率对散列进行排序?有没有比我的更好的方法?
How do I sort hash based on frequency of occurrences in Ruby? Is there a better way than what I have?
我正在尝试编写一种方法,该方法接受一个字符串并按降序输出字符在哈希中出现的次数。
我可以为每个单词做这个。我需要为每个角色做这个。
string = "Apple, Banana, Time, Time, Time, Banana Apple, Time."
def cw(string)
w = string.gsub(/\W/," ").split
freq =
Hash[w.group_by { |x| x }.map { |k, vs| [k, vs.length] }.sort_by { |k, length| -length }]
return freq
end
puts cw(string)
期望:A => 8; B => 2; ..等等
实际:{"Time"=>4,"Apple"=>2,"Banana"=>2}
您需要确保按空字符串拆分:
w = string.gsub(/\W/," ").split("")
我假设每个字母的计数都是大小写无关的。
str = "Apple, Banana, Time, Time, Time, Banana Apple, Time."
您说要按 "the number of occurrences a character" 排序(例如,不是 "letter")。您可以按如下方式进行。
h = str.downcase.
each_char.
each_with_object(Hash.new(0)) { |c,h| h[c] += 1 }.
sort_by { |_,v| -v }.
to_h
#=> {"a"=>8, " "=>7, "e"=>6, ","=>6, "i"=>4, "t"=>4, "m"=>4, "p"=>4,
# "n"=>4, "b"=>2, "l"=>2, "."=>1}
如果只需要字母数,则需要多一步:
h.select { |k,_| k.match?(/[a-z]/i) }
#=> {"a"=>8, "e"=>6, "i"=>4, "t"=>4, "m"=>4, "p"=>4, "n"=>4, "b"=>2, "l"=>2}
这最后一步当然可以链接到上面 h
的计算。
步骤如下
a = str.downcase
#=> "apple, banana, time, time, time, banana apple, time."
b = a.each_char
#=> #<Enumerator: "apple, banana, time, time, time, banana apple,
# time.":each_char>
我们可以看到枚举器 c
将生成并通过将其转换为数组传递给块的元素。
b.to_a
#=> ["a", "p", "p", "l", "e", ",", " ", "b", "a", "n", "a", "n",
# "a", ",", " ", "t", "i", "m", "e", ",", " ", "t", "i", "m",
# "e", ",", " ", "t", "i", "m", "e", ",", " ", "b", "a", "n",
# "a", "n", "a", " ", "a", "p", "p", "l", "e", ",", " ", "t",
# "i", "m", "e", "."]
继续,
c = b.each_with_object(Hash.new(0)) { |c,h| h[c] += 1 }
#=> {"a"=>8, "p"=>4, "l"=>2, "e"=>6, ","=>6, " "=>7, "b"=>2,
# "n"=>4, "t"=>4, "i"=>4, "m"=>4, "."=>1}
d = c.sort_by { |_,v| -v }
#=> [["a", 8], [" ", 7], ["e", 6], [",", 6], ["i", 4], ["t", 4],
# ["m", 4], ["p", 4], ["n", 4], ["b", 2], ["l", 2], [".", 1]]
e = d.to_h
#=> {"a"=>8, " "=>7, "e"=>6, ","=>6, "i"=>4, "t"=>4, "m"=>4,
# "p"=>4, "n"=>4, "b"=>2, "l"=>2, "."=>1}
e.select { |k,_| k.match?(/[a-z]/i) }
#=> {"a"=>8, "e"=>6, "i"=>4, "t"=>4, "m"=>4, "p"=>4, "n"=>4,
# "b"=>2, "l"=>2}
如果a
的计算改为如下,最后一步可以省略。
a = str.downcase.gsub(/[^a-z]/i, '')
#=> "applebananatimetimetimebananaappletime
尝试以下面的方式使用 gsub。
string = "Apple, Banana, Time, Time, Time, Banana Apple, Time."
def cw(string)
a = string.gsub(/[aA]/).count
b = string.gsub(/[bB]/).count
Hash['A', a, 'B', b]
end
cw(string)
=> {"A"=>8, "B"=>2}
我正在尝试编写一种方法,该方法接受一个字符串并按降序输出字符在哈希中出现的次数。
我可以为每个单词做这个。我需要为每个角色做这个。
string = "Apple, Banana, Time, Time, Time, Banana Apple, Time."
def cw(string)
w = string.gsub(/\W/," ").split
freq =
Hash[w.group_by { |x| x }.map { |k, vs| [k, vs.length] }.sort_by { |k, length| -length }]
return freq
end
puts cw(string)
期望:A => 8; B => 2; ..等等
实际:{"Time"=>4,"Apple"=>2,"Banana"=>2}
您需要确保按空字符串拆分:
w = string.gsub(/\W/," ").split("")
我假设每个字母的计数都是大小写无关的。
str = "Apple, Banana, Time, Time, Time, Banana Apple, Time."
您说要按 "the number of occurrences a character" 排序(例如,不是 "letter")。您可以按如下方式进行。
h = str.downcase.
each_char.
each_with_object(Hash.new(0)) { |c,h| h[c] += 1 }.
sort_by { |_,v| -v }.
to_h
#=> {"a"=>8, " "=>7, "e"=>6, ","=>6, "i"=>4, "t"=>4, "m"=>4, "p"=>4,
# "n"=>4, "b"=>2, "l"=>2, "."=>1}
如果只需要字母数,则需要多一步:
h.select { |k,_| k.match?(/[a-z]/i) }
#=> {"a"=>8, "e"=>6, "i"=>4, "t"=>4, "m"=>4, "p"=>4, "n"=>4, "b"=>2, "l"=>2}
这最后一步当然可以链接到上面 h
的计算。
步骤如下
a = str.downcase
#=> "apple, banana, time, time, time, banana apple, time."
b = a.each_char
#=> #<Enumerator: "apple, banana, time, time, time, banana apple,
# time.":each_char>
我们可以看到枚举器 c
将生成并通过将其转换为数组传递给块的元素。
b.to_a
#=> ["a", "p", "p", "l", "e", ",", " ", "b", "a", "n", "a", "n",
# "a", ",", " ", "t", "i", "m", "e", ",", " ", "t", "i", "m",
# "e", ",", " ", "t", "i", "m", "e", ",", " ", "b", "a", "n",
# "a", "n", "a", " ", "a", "p", "p", "l", "e", ",", " ", "t",
# "i", "m", "e", "."]
继续,
c = b.each_with_object(Hash.new(0)) { |c,h| h[c] += 1 }
#=> {"a"=>8, "p"=>4, "l"=>2, "e"=>6, ","=>6, " "=>7, "b"=>2,
# "n"=>4, "t"=>4, "i"=>4, "m"=>4, "."=>1}
d = c.sort_by { |_,v| -v }
#=> [["a", 8], [" ", 7], ["e", 6], [",", 6], ["i", 4], ["t", 4],
# ["m", 4], ["p", 4], ["n", 4], ["b", 2], ["l", 2], [".", 1]]
e = d.to_h
#=> {"a"=>8, " "=>7, "e"=>6, ","=>6, "i"=>4, "t"=>4, "m"=>4,
# "p"=>4, "n"=>4, "b"=>2, "l"=>2, "."=>1}
e.select { |k,_| k.match?(/[a-z]/i) }
#=> {"a"=>8, "e"=>6, "i"=>4, "t"=>4, "m"=>4, "p"=>4, "n"=>4,
# "b"=>2, "l"=>2}
如果a
的计算改为如下,最后一步可以省略。
a = str.downcase.gsub(/[^a-z]/i, '')
#=> "applebananatimetimetimebananaappletime
尝试以下面的方式使用 gsub。
string = "Apple, Banana, Time, Time, Time, Banana Apple, Time."
def cw(string)
a = string.gsub(/[aA]/).count
b = string.gsub(/[bB]/).count
Hash['A', a, 'B', b]
end
cw(string)
=> {"A"=>8, "B"=>2}