Justin
Justin

Reputation: 3

How do I get this block of ruby to add each individual hash into an array instead of just adding one hash multiple times?

@session is formatted as

[
  ['time','action','user'],
  ['time','action','user'],
  ...
]

and I'm trying to create an array that has those array elements but as hashes of {:time=>"time, :action=>"action", :user=>"user"}. The puts sessions line outputs each line as I desire, but when I try to capture those hashes into sessions_array I receive an array of only one hash repeated many times and not the unique hashes that puts is outputting.

sessions = Hash.new
sessions_array = Array.new

@session.each_with_index { |element, index|
  next_element = @session[index+1]

  sessions[:time] = element[0]
  sessions[:action] = element[1]
  sessions[:user] = element[2]

  sessions_array << sessions
  puts sessions
}

puts sessions_array

Upvotes: 0

Views: 55

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110725

Perhaps you are looking for something like the following.

Code

def hashify(data, keys)     
  data.map { |row| keys.zip(row).to_h }
end

Example

data = [
  %w| 11:00 pummel Billy-Bob |,
  %w| 02:00 maim Trixie |,
  %w| 19:00 kill Bill |
]
  #=> [["11:00", "pummel", "Billy-Bob"],
  #    ["02:00", "maim", "Trixie"],
  #    ["19:00", "kill", "Bill"]]

keys = [:time, :action, :user] 

hashify(data, keys)
  #=> [{:time=>"11:00", :action=>"pummel", :user=>"Billy-Bob"},
  #    {:time=>"02:00", :action=>"maim", :user=>"Trixie"},
  #    {:time=>"19:00", :action=>"kill", :user=>"Bill"}]

I have chosen to make data and keys arguments of the method so that those parameters can be modified without affecting the method itself.

Note that each of the three elements of:

data.map { |row| keys.zip(row) }
  #=> [[[:time, "11:00"], [:action, "pummel"], [:user, "Billy-Bob"]],
  #    [[:time, "02:00"], [:action, "maim"], [:user, "Trixie"]],
  #    [[:time, "19:00"], [:action, "kill"], [:user, "Bill"]]]

is converted to a hash using the method Array#to_h. See also Array#zip.

Upvotes: 0

Jordan Running
Jordan Running

Reputation: 106077

Create sessions inside of the each_with_index block instead of outside:

sessions_array = []

@session.each do |element|
  sessions = {
    time: element[0],
    action: element[1],
    user: element[2],
  }
  sessions_array << sessions
end

puts sessions_array

However, this can be done much more succinctly. When you're turning an array into another array with the same number of elements you almost always want to use map. Also, in a Ruby block you can extract the elements from an array by specifying multiple names in its arguments (|foo, bar, ...|).

This code is equivalent to the above:

sessions_array = @session.map do |time, action, user|
  { time: time, action: action, user: user }
end

You can see both of these snippets in action on repl.it here: https://repl.it/@jrunning/NavyImmaculateShockwave

Upvotes: 1

Related Questions