代码之家  ›  专栏  ›  技术社区  ›  Phellipe Brasiliano

如何迭代集合哈希

  •  0
  • Phellipe Brasiliano  · 技术社区  · 7 年前

    我有一个散列,以游戏玩家的名字作为键,还有一个集合对象,其中包含每个被击败的其他玩家的名字作为值。集合初始化为空,然后随机挑选两个玩家并相互攻击,获胜者将获得另一个玩家的密钥添加到其集合中,表示对他们的胜利。一旦胜利确立,球员们就不能再互相争斗了。最后,一个打败了另一个的球员也应该在他的场上有被另一个打败的球员,以及其他被他们打败的球员,以此类推。

    在给定的比赛情况下,有5名球员,克劳迪娅、罗莎、鲍勃、卡洛斯和蒂姆。假设Rosa打败了Bob,Bob打败了Carlos,Claudia打败了Tim,此时给定的数据如下所示:

    @match_data = {"claudia"=>#<Set: {"tim">,
                   "rosa"=>#<Set: {"bob", "carlos"}>,
                   "bob"=>#<Set: {"carlos"},
                   "carlos"=>#<Set: {},
                   "tim"=>#<Set: {}}
    

    因此,在这一点上,克劳迪娅对蒂姆取得了胜利,因此他们将不会再有另一场战斗,罗莎对鲍勃和卡洛斯取得了胜利,因此她将不再需要与他们战斗,而鲍勃对卡洛斯,他们也不会战斗。想象一下,在这之后,Bob打败了Claudia,此时所需的数据应该是:

    @match_data = {"claudia"=>#<Set: {"tim"}>,
                   "rosa"=>#<Set: {"bob", "carlos", "claudia", "tim"}>,
                   "bob"=>#<Set: {"carlos", "claudia", "tim"},
                   "carlos"=>#<Set: {},
                   "tim"=>#<Set: {}}
    

    当鲍勃击败克劳迪亚时,他不仅获得了对她的胜利,而且还获得了对之前被击败的蒂姆的胜利,更重要的是,罗莎获得了对克劳迪亚和蒂姆的胜利,因为她已经获得了对鲍勃的胜利。所以在这种情况下,罗莎赢得了比赛,鲍勃是第二名,其他人还在玩。这可能会变得更复杂,因为玩家的数量不受限制。

    我试图克服的问题是创建一个更新游戏状态的函数。每次比赛结束时,这段代码都会查看match_数据,并找出比赛结果取得了哪些胜利。这段代码是我的一次尝试:

    def update_set(key)
      store = Set.new
      @match_data[key].each { |value| store.merge @match_data[value] }
      if store.size > 0
        store.each { |value| update_set(value) }
      end
      @match_data[key].merge store
    end
    
    @match_data.sort.map do |key, set|
      update_set(key)
    end
    

    我的其他尝试得到一个错误,说我走得太深了,或者我不能在循环期间迭代哈希。或者,我可以尝试使用另一种数据结构,但我不知道是哪种。

    编辑:为了清晰起见,我编辑了原始问题,因为运行代码时不清楚我想要的输出是什么。尽管如此,@ddubs给出的答案对我的代码非常有效。

    此外,我想指出一个错误,在我的给定示例中,在我的程序中,数据永远不会像第一个代码段中所示那样完全转变,因为所需的函数将始终在每次战斗之间运行,刷新字典的状态。我想我不想写太多无用的信息,使我的问题比它需要的更复杂,但我最终压制了重要的信息。

    如果需要,我可以发布整个程序逻辑,但我认为这不是必要的。

    EDIT2:添加了整个游戏的逻辑,因为我发现它仍然不够清晰,@ddubs给出的解决方案仍然有效,但也许有人可以提供更好的东西,现在所有的信息都给出了。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Derek Wright    7 年前

    布景似乎让这件事显得有些奇怪,或者这只是布景 @match_data 对象无论如何,这个函数必须应用于每个玩家及其对应的集合。它还需要您将匹配数据传递给它:

    def compile_sets(set, data, results = Set.new)
      set.each do |s|
        results << s
        results << compile_sets(data[s], data, results)
      end
      results.flatten
    end
    

    示例用法:

    results = @match_data.map { |player,set| { player => compile_sets(set, @match_data) } }
    
    p results
    

    返回:

    [
      {"carlos"=>#<Set: {}>},
      {"bob"=>#<Set: {"carlos", "claudia"}>},
      {"lisa"=>#<Set: {"bob", "carlos", "claudia"}>},
      {"tim"=>#<Set: {"lisa", "bob", "carlos", "claudia"}>},
      {"mary"=>#<Set: {"lisa", "bob", "carlos", "claudia"}>},
      {"rosa"=>#<Set: {"tim", "lisa", "bob", "carlos", "claudia"}>}, 
      {"claudia"=>#<Set: {}>}
    ]