3

I'm trying to rearrange data in array to be in hash format but I pretty messed up using nested if

Sample Data

[
  ["England", "London", "University College London ", "Faculty of Law"], 
  ["England", "London", "University College London ", "Faculty of Engineering"], 
  ["England", "London", "Imperial College London", "Faculty of Medicine"], 
  ["England", "Manchester", "University of Manchester", "Faculty of Engineering"]
]

Expected Output

{:name=>"England", 
:level=>1, 
:children=>[{:name=>"London", 
             :level=>2, 
             :children=>[{:name=>"University College London ", 
                          :level=>3, 
                          :children=>[{:name=>"Faculty of Law", 
                                       :level=>4, 
                                       :children=>[]},
                                      {:name=>"Faculty of Engineering", 
                                       :level=>4, :children=>[]}]},
                         {:name=>"Imperial College London", 
                          :level=>3, 
                          :children=>[{:name=>"Faculty of Engineering", 
                                       :level=>4, 
                                      :children=>[]}]
                         }]
           }]
}

hope I have provide clear explaination

ps. edit to show what I've tried first i make array of hash then do something like this I thought it wouldn't be confused this much

result = []
arr.each do |b|
  if result.any? {|r| r[:name] == b[:name]}
    if result.first[:children].any? {|r| r[:name] == b[:children].first[:name]}
      if result.first[:children].any?{|c| c[:children].any? {|r| r[:name] == b[:children].first[:children].first[:name] && c[:name] == b[:children].first[:name] }}
        if result.first[:children].any? {|r| r[:children].any? {|c| c[:children].any?{|k| k[:name] == b[:children].first[:children].first[:children].first[:name] && (c[:name] == b[:children].first[:children].first)}}}

        else
          result.first[:children].any?{|c| c[:children].any? {|r| r[:name] == b[:children].first[:children].first[:name] ; r[:children] << b[:children].first[:children].first[:children].first}}

        end #fourth
      else
        result.first[:children].any? {|r| r[:name] == b[:children].first[:name]; r[:children] << b[:children].first[:children].first}
      end 
    else
      result.any? {|r| r[:name] == b[:name] ; r[:children] << b[:children].first}
    end 
  else result << b 
  end
end
4
  • 3
    What have u tried so far? Post your code. Commented Mar 15, 2018 at 12:40
  • That looks pretty messy to me. Would it not be better to use four hashes (i.e. { country: "England", city: "London", institution: "University College London ", faculty: "Faculty of Law" }) and use these however's needed? If not, some context around why this format is needed would be handy :) Commented Mar 15, 2018 at 12:46
  • 1
    What happened to Manchester? I am assuming it should be a level 1 child Commented Mar 15, 2018 at 13:34
  • Your expected output (being a hash) can only handle a single 1st level / country. Is that intended? What happens if there's an entry for another country? Commented Mar 15, 2018 at 13:49

2 Answers 2

2

You could do this recursive like this:

def map_objects(array, level = 1)
  new_obj = []
  array.group_by(&:shift).each do |key, val|
    new_obj << {:name=>key, :level=>level, :children=>map_objects(val, level + 1)} if key
  end
  new_obj
end

For your array it will return like this:

# [
# {:name => "England", :level => 1, :children => [
#     {:name => "London", :level => 2, :children => [
#         {:name => "University College London ", :level => 3, :children => [
#             {:name => "Faculty of Law", :level => 4, :children => []
#             },
#             {:name => "Faculty of Engineering", :level => 4, :children => []
#             }]
#         },
#         {:name => "Imperial College London", :level => 3, :children => [
#             {:name => "Faculty of Medicine", :level => 4, :children => []
#             }]
#         }]
#     },
#     {:name => "Manchester", :level => 2, :children => [
#         {:name => "University of Manchester", :level => 3, :children => [
#             {:name => "Faculty of Engineering", :level => 4, :children => []
#             }]
#         }]
#     }]
# }
# ]
Sign up to request clarification or add additional context in comments.

Comments

0

I hope the following code can help you:

input = [
    ["England", "London", "University College London ", "Faculty of Law"], 
    ["England", "London", "University College London ", "Faculty of Engineering"], 
    ["England", "London", "Imperial College London", "Faculty of Medicine"], 
    ["England", "Manchester", "University of Manchester", "Faculty of Engineering"]
  ]

output = Array.new

input.each do |i|
    if output.select { |out| out[:name] == i[0] }.empty?
        output << { :name => i[0], :level => 1, :child => [] }
    end

    level1 = output.select { |out| out[:name] == i[0] }
    level1.each do |l1|
        if l1[:child].select { |l| l[:name] == i[1] }.empty?
            l1[:child] << { :name => i[1], :level => 2, :child => [] }
        end
    end

    level1.each do |l1|
        level2 = l1[:child].select { |l| l[:name] == i[1] }
        level2.each do |l2|
            if l2[:child].select { |l| l[:name] == i[2] }.empty?
                l2[:child] << { :name => i[2], :level => 3, :child => [] } 
            end
        end
    end

    level1.each do |l1|
        level2 = l1[:child].select { |l| l[:name] == i[1] }
        level2.each do |l2|
            level3 = l2[:child].select { |l| l[:name] == i[2] }
            level3.each do |l3|
                if l3[:child].select { |l| l[:name] == i[3] }.empty?
                    l3[:child] << { :name => i[3], :level => 4 } 
                end
            end
        end
    end
end

puts output

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.