36068


初めてご質問させて頂きます。  
現在、rubyにて複数ユーザーの親子関係を表すハッシュを作成する関数を作成しているのですが、シンボルを用いたハッシュへの代入にて失敗しています。

[code]

        def createChild(child_id)
          return {
            person_id: child_id,
            children: []
          };
        end
    
        def searchTree(rootTree, id)
          rootTree[:children].map{|tree|
            if tree[:person_id] == id
              return tree
            end
          }
          rootTree[:children].map{|tree|
            searchTree(tree, id)
          }
        end
    
        def putChild(root_tree, child_id, parent_id)
          if parent_id == 0
            root_tree[:children] << createChild(child_id)
          else
            target = searchTree(root_tree, parent_id)
            target[:children] << createChild(child_id) #エラー地点
          end
        end
    
        tree_map = {person_id: nil, children: []}
        putChild(tree_map, 1, 0)
        putChild(tree_map, 2, 0)
        putChild(tree_map, 3, 1)
        putChild(tree_map, 4, 1)
        putChild(tree_map, 5, 1)
        puts tree_map
        puts 'try'
        putChild(tree_map, 6, 3)
        puts tree_map
    
[/code]

メソッド`putChild`を計6回呼び出していますが、6回目の実行時に `#エラー地点` にてエラーが発生しております。

上記ファイルの実行結果が

[code]

    {:person_id=>nil, :children=>[{:person_id=>1, :children=>[{:person_id=>3, :children=>[]}, {:person_id=>4, :children=>[]}, {:person_id=>5, :children=>[]}]}, {:person_id=>2, :children=>[]}]}
    try
    sample.rb:24:in `[]': no implicit conversion of Symbol into Integer (TypeError)
    from sample.rb:24:in `putChild'
    from sample.rb:36:in `<main>'
    
[/code]

です。

同じ呼び出し方で5回成功して、6回目が失敗するのがどうにも原因がわからず、もしお判りの方がいらっしゃいましたらご教示頂けますと幸いです。

よろしくお願いいたします。


CC BY-SA 3.0
2017-07-03T09:26:48.450
36066
2017-07-04T01:16:38.343
2017-07-04T01:16:38.343
19110
24190
question
ruby ハッシュ
シンボルを用いたハッシュからの呼び出しに失敗する


`searchTree` は

[code]

    def searchTree(rootTree, id)
      # returns tree
      rootTree[:children].map{|tree|
        if tree[:person_id] == id
          return tree
        end
      }
      # returns tree[]
      rootTree[:children].map{|tree|
        searchTree(tree, id)
      }
    end
    
[/code]

となってしまっており、型が一致していません

[code]

      rootTree[:children].each{|tree|
        found = searchTree(tree, id)
        return found if found
      }
    
[/code]

のようにするなどして型を合わせる必要があります

クラスを使ったほうが、型違いに気づきやすくなります

[code]

    class Child
      attr_accessor :person_id, :children
    
      def initialize(person_id)
        @person_id = person_id
        @children = []
      end
    
      def search(person_id)
        found = @children.find { |child| child.person_id == person_id }
        return found if found
        @children.each { |child|
          found = child.search(person_id)
          return found if found
        }
        return nil
      end
    
      def add(child_id, parent_id)
        found = search(parent_id)
        found.children << Child.new(child_id) if found
      end
    end
    
    tree_map = Child.new(nil)
    tree_map.children << Child.new(0)
    tree_map.add(1, 0)
    tree_map.add(2, 0)
    tree_map.add(3, 1)
    tree_map.add(4, 1)
    tree_map.add(5, 1)
    tree_map.add(6, 3)
    
[/code]

といった感じにするとよいと思います


CC BY-SA 3.0
2017-07-03T10:22:51.627
36068
2017-07-03T10:22:51.627
9796
36066
answer