Как отсортировать хеш по частоте появления в Ruby?Есть ли лучший способ, чем у меня? - PullRequest
0 голосов
/ 22 декабря 2018

Я пытаюсь написать метод, который принимает строку и выводит количество вхождений, которые символ отображает в хэше в порядке убывания.

Я могу сделать это для каждого из слов.Мне нужно сделать это для каждого персонажа.

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;..etc.

Факт: {"Time" => 4, "Apple" => 2, "Banana" => 2}

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018

Я предполагаю, что количество каждой буквы не зависит от регистра.

str = "Apple, Banana, Time, Time, Time, Banana Apple, Time."

Вы сказали, что сортируете по «количеству вхождений на символ» (например, не по «букве»).Вы можете сделать это следующим образом.

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
0 голосов
/ 22 декабря 2018

Попробуйте использовать 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}
0 голосов
/ 22 декабря 2018

Вы должны убедиться, что вы разделяете на пустую строку:

w = string.gsub(/\W/," ").split("")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...