Вот один из способов сделать это.
Код
def max_host(hash)
hash.each_with_object(Hash.new(0)) { |(_,v),h| h[v[:host]] += 1 }
.max_by { |_,v| v }
.first
end
Пример
Давайте рассмотрим упрощенный пример ниже. Обратите внимание, что я изменил, например, :host = \"host.10\"
на :host = "host.10"
, поскольку первый не является правильным синтаксисом. Вы можете написать строку как '\"host.10\"
(=> "\\\"host.10\\\""
), но я предполагаю, что вы просто хотите "host.10"
. Код тот же для обоих.
hash = {
0 => {
:method=>"POST",
:host =>"host.8"
},
1 => {
:method=>"GET",
:host =>"host.10"
},
2 => {
:method=>"POST",
:host =>"host.10"
}
}
max_host(hash)
#=> "host.10"
Объяснение
Для примера hash
выше,
enum = hash.each_with_object(Hash.new(0))
#=> #<Enumerator: {
# 0=>{:method=>"POST", :host=>"host.8"},
# 1=>{:method=>"GET", :host=>"host.10"},
# 2=>{:method=>"POST", :host=>"host.10"}}:each_with_object({})>
Перечислитель будет вызывать метод Hash#each пройти каждый элемент счетчику в блок. Мы можем видеть, что эти элементы путем преобразования нумератора в массив:
enum.to_a
#=> [[[0, {:method=>"POST", :host=>"host.8"}], {}],
# [[1, {:method=>"GET", :host=>"host.10"}], {}],
# [[2, {:method=>"POST", :host=>"host.10"}], {}]]
Пустой хеш показан в первом элементе является начальным значением хэша созданного
Hash.new(0)
Это создает хэш h
со значением по умолчанию, равным нулю. Таким образом, если у h
нет ключа k
, h[k]
вернет значение по умолчанию (0
), но (важно!) Это не изменит хэш.
Первое значение, переданное в блоке
[[0, {:method=>"POST", :host=>"host.8"}], {}]
Это разлагают (или «многозначной») на отдельные объекты, которые назначены на три блока переменных:
k => 0
v => {:method=>"POST", :host=>"host.8"}
h => Hash.new(0)
Затем мы выполняем :
h[v[:host]] += 1
который
h["host.8"] += 1
который является сокращением для
h["host.8"] = h["host.8"] + 1
[За исключением: вы, возможно, заметили, что в коде показывает блочные переменные |(_,v),h|
, в то время как выше я имею в виду их выше как |(k,v),h|
. Я мог бы использовать последнее, но поскольку k
не является ссылкой в блоке, я решил заменить его «заполнителем» _
. Это гарантирует k
не будет ссылаться, а также говорит, что любые читатели я не использую то, что бы быть первой переменной блок.]
Как h
не имеет ключа "host.8"
, h["host.8"]
справа от =
возвращает значение по умолчанию значение:
h["host.8"] = 0 + 1
#=> 1
так что теперь
h #=> {"host.8"=>1}
Второй элемент передается в блок является
[[1, {:method=>"GET", :host=>"host.10"}], {"host.8"=>1}]
так блочные переменные становятся:
v => {:method=>"GET", :host=>"host.10"}
h => {"host.8"=>1}
Обратите внимание, что хэш h
был обновлен. Мы выполняем
h[v[:host]] += 1
#=> h["host.10"] += 1
#=> h["host.10"] = h["host.10"] + 1
#=> h["host.10"] = 0 + 1
#=> 1
так что теперь
h #=> {"host.8"=>1, "host.10"=>1}
Наконец, блок-переменные присваиваются значения
v = {:method=>"POST", :host=>"host.10"}
h => {"host.8"=>1, "host.10"=>1}
так
h[v[:host]] += 1
#=> h["host.10"] += 1
#=> h["host.10"] = h["host.10"] + 1
#=> h["host.10"] = 1 + 1
#=> 2
h #=> {"host.8"=>1, "host.10"=>2}
и значение h
то возвращается б y метод.
Возможный дубликат [Поиск по хэшу, содержащему хэши] (http://stackoverflow.com/questions/27126400/search-within-a-hash-containing-hashes) –
Возможно, вы захотите сделать редактирование, чтобы исправить проблема форматирования строки, о которой я упоминал в своем ответе. Я ожидаю, что это приведет к сокращению голосов и голосам. Я удалю этот комментарий после того, как вы его увидели, - ответ не нужен. –
Готово, я обновил свой вопрос. – Mich