Home > Back-end >  Ruby_How to find values subscription in hash
Ruby_How to find values subscription in hash

Time:04-06

how to convert line 1 to line 2

h1 = {"one"=>[1,2,3,4], "two"=>[4,5,6,7], "three"=>[7,8,9,1]}

h2 ={4=>["one","two"],7=>["two","three"],1=>["one","three"]}

CodePudding user response:

h1.each_with_object(Hash.new { |h,k| h[k] = [] }) do |(k,v), h|
  v.each { |n| h[n] << k }
end.select { |_,v| v.size > 1 }
  #=> {1=>["one", "three"], 4=>["one", "two"], 7=>["two", "three"]}

This uses the form of Hash::new that takes a block and no argument. If h = Hash.new { |h,k| h[k] = [] } then, possibly after key/value pairs have been added to h, if h does not have a key n, h[n] << n causes h[n] = [] to be executed prior to h[n] << k.

I can best explain the calculations by sale code with puts statements and then executing the code for the example.

h1.each_with_object(Hash.new { |h,k| h[k] = [] }) do |(k,v), h|
  puts "\nk = #{k}, v = #{v}, h = #{h}"
  v.each do |n|
    puts "  n = #{n}"
    puts "    Execute h[#{n}] = [] because h does not have a key #{k}" unless
      h.key(n) unless h.key?(n)
    h[n] << k
    puts "    h after h[#{n}] << #{k} = #{h}"
  end
end
  .tap { |h| puts "\nh before select = #{h}" }
  .select { |_,v| v.size > 1 }
  #=> {1=>["one", "three"], 4=>["one", "two"], 7=>["two", "three"]}

displays:

k = one, v = [1, 2, 3, 4], h = {}
  n = 1
    Execute h[1] = [] because h does not have a key one
    h after h[1] << one = {1=>["one"]}
  n = 2
    Execute h[2] = [] because h does not have a key one
    h after h[2] << one = {1=>["one"], 2=>["one"]}
  n = 3
    Execute h[3] = [] because h does not have a key one
    h after h[3] << one = {1=>["one"], 2=>["one"], 3=>["one"]}
  n = 4
    Execute h[4] = [] because h does not have a key one
    h after h[4] << one = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one"]}
k = two, v = [4, 5, 6, 7], h = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one"]}
  n = 4
    h after h[4] << two = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one", "two"]}
  n = 5
    Execute h[5] = [] because h does not have a key two
    h after h[5] << two = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one", "two"],
      5=>["two"]}
  n = 6
    Execute h[6] = [] because h does not have a key two
    h after h[6] << two = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one", "two"],
      5=>["two"], 6=>["two"]}
  n = 7
    Execute h[7] = [] because h does not have a key two
    h after h[7] << two = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one", "two"],
      5=>["two"], 6=>["two"], 7=>["two"]}
k = three, v = [7, 8, 9, 1], h = {1=>["one"], 2=>["one"], 3=>["one"],
  4=>["one", "two"], 5=>["two"], 6=>["two"], 7=>["two"]}
  n = 7
    h after h[7] << three = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one", "two"],
      5=>["two"], 6=>["two"], 7=>["two", "three"]}
  n = 8
    Execute h[8] = [] because h does not have a key three
    h after h[8] << three = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one", "two"],
      5=>["two"], 6=>["two"], 7=>["two", "three"], 8=>["three"]}
  n = 9
    Execute h[9] = [] because h does not have a key three
    h after h[9] << three = {1=>["one"], 2=>["one"], 3=>["one"], 4=>["one", "two"],
      5=>["two"], 6=>["two"], 7=>["two", "three"], 8=>["three"], 9=>["three"]}
  n = 1
    h after h[1] << three = {1=>["one", "three"], 2=>["one"], 3=>["one"],
      4=>["one", "two"], 5=>["two"], 6=>["two"], 7=>["two", "three"], 8=>["three"],
      9=>["three"]}
h before select = {1=>["one", "three"], 2=>["one"], 3=>["one"], 4=>["one", "two"],
  5=>["two"], 6=>["two"], 7=>["two", "three"], 8=>["three"], 9=>["three"]}
​
  • Related