2011-05-14 101 views
1

大家好我已经让自己变得相当复杂(至少对我来说)构造。 我有一个哈希,看起来像(例如):红宝石哈希:从排序值中获取一组密钥

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

(注:它是一个哈希,所以它没有排序尚)

现在我想什么: 有一个循环开始深度= 0具有一组深度为0或更小的所有状态, 环路的下一次迭代,具有深度为1或更小的所有状态的一组等等。

什么是获得这种构造的简洁方法?

如果我的问题不清楚,请让我知道。

回答

4

你可以只使用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"] 
+0

谢谢,我测试过了,它效果很好!我坚持使用J -.- L的解决方案,因为它的结果更接近我需要的 – SirLenz0rlot 2011-05-14 11:57:32

+0

注意:我无法编辑您的评论,但是(&:first)后面有一个额外的“}” }''' – SirLenz0rlot 2011-05-14 12:04:31

+0

是的,谢谢。我从一个'{}'块重写了一个'do ... end',因为在这里阅读起来比较容易,然后忘记了一个大括号 – 2011-05-14 12:45:29

1
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 ;) 
} 
+0

有一个在代码中的错误: 做'(0..level)。每个{| i | ..'导致depths_with_states [i]具有深度为i +的所有状态集合而不是0 ..i – SirLenz0rlot 2011-05-14 12:25:51

+0

对不起,修正了它。 – 2011-05-14 13:23:11

1

下面是之前1.8.7(当加入Enumerable#group_by)为Ruby工作的变化:

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