Ruby Hashes: получение набора ключей из отсортированных значений - PullRequest
1 голос
/ 14 мая 2011

Привет всем, я сделал себе довольно сложную (по крайней мере, для меня) конструкцию. У меня есть хеш, похожий (пример):

states_with_depths = {
 #State => depth
 "S0" => 0,
 "S1" => 1,
 "S2" => 2,
 "S3" => 2,
 "S4" => 2,
 "S5" => 3
}

(примечание: это хэш, поэтому он еще не отсортирован)

Теперь то, что я хотел бы: Наличие цикла, начинающегося с глубины = 0, с набором всех состояний, имеющих глубину 0 или менее, следующая итерация цикла с набором всех состояний глубиной 1 или менее и т. д.

Какой был бы изящный способ получить такую ​​конструкцию?

Пожалуйста, дайте мне знать, если мой вопрос неясен.

Ответы [ 3 ]

4 голосов
/ 14 мая 2011

Вы можете просто использовать group_by со значением:

>> states_with_depths.group_by { |k,v| v }
 #=> {0=>[["S0", 0]], 1=>[["S1", 1]], 2=>[["S2", 2], ["S3", 2], ["S4", 2]], 3=>[["S5", 3]]}

Это также можно сократить до:

states_with_depths.group_by(&:last)

Чтобы использовать это, вы можете сделать что-то вроде:

states_with_depths.group_by(&:last).each do |depth, arrs| 
  puts "Values with depth #{depth}: #{arrs.map(&:first)}"                                                                                                                        
end

Какие выходы:

Values with depth 0: ["S0"]
Values with depth 1: ["S1"]
Values with depth 2: ["S2", "S3", "S4"]
Values with depth 3: ["S5"]
1 голос
/ 14 мая 2011

Вот вариант, который работает для Ruby до 1.8.7 (когда было добавлено Enumerable#group_by):

states_by_depth = Hash.new{|h,depth| h[depth]=[] }
states_with_depths.each{ |state,depth| states_by_depth[depth] << state }
#=> {0=>["S0"], 1=>["S1"], 2=>["S3", "S4", "S2"], 3=>["S5"]}
min_depth = states_by_depth.keys.min
max_depth = states_by_depth.keys.max
min_depth.upto(max_depth) do |depth|
  next unless states = states_by_depth[depth]
  puts "Depth: #{depth}"
  states.each{ |state| puts "..#{state}" }
end
#=> Depth: 0
#=> ..S0
#=> Depth: 1
#=> ..S1
#=> Depth: 2
#=> ..S3
#=> ..S4
#=> ..S2
#=> Depth: 3
#=> ..S5
1 голос
/ 14 мая 2011
require 'set'

depths_with_states = []

max_level = states_with_depths.max_by{|e|e[1]}[1]

states_with_depths.map{ |state, level|
  (level..max_level).each{ |i|
    depths_with_states[i] ||= Set.new  # ...or just array
    depths_with_states[i] << state
  }
}

depths_with_states.each{ |states|
  # do whatever you want to do ;)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...