Hernan Acosta
Hernan Acosta

Reputation: 397

how to construct a hash with multiples nested in ruby

I want to construct a hash, the problem is that I have some customers that are buyers and others that are sellers that can have the same name and I need to group them in a hash by name. Something like this:

customers = {"name1": {"buyers": [id11,..,id1n], "sellers": [ids1,..,ids1n]},
             "name2": {"buyers": [id2,..,id], "sellers": [id1,..,idn] }}

The name is the key and the value is the hash with buyers and sellers, but I don't know how to initialize the hash and how to add a new key, value. Suppose that I have the Customer.all and I can for example ask:

Customer.all do |customer|
  if customer.buyer?
    puts customer.name, customer.id
  end
end

Upvotes: 0

Views: 53

Answers (2)

Simple Lime
Simple Lime

Reputation: 11035

You can use the block form of Hash.new to set up each hash key that does not have a corresponding entry, yet, to have a hash as its value with the 2 keys you need:

customers = Hash.new do |hash, key|
  hash[key] = { buyers: [], sellers: [] }
end

and then you can loop through and assign to either the :buyers or :sellers subarray as needed:

Customer.all do |customer|
  group = customers[customer.name] # this creates a sub hash if this is the first
                                   # time the name is seen
  group = customer.buyer? ? group[:buyers] : group[:sellers]

  group << customer.id
end

p customers
# Sample Output (with newlines added for readability):
# {"Customer Group 1"=>{:buyers=>[5, 9, 17], :sellers=>[1, 13]},
#  "Customer Group 2"=>{:buyers=>[6, 10], :sellers=>[2, 14, 18]},
#  "Customer Group 3"=>{:buyers=>[7, 11, 15], :sellers=>[3, 19]},
#  "Customer Group 0"=>{:buyers=>[20], :sellers=>[4, 8, 12, 16]}}

For those following along at home, this is the Customer class I used for testing:

class Customer
  def self.all(&block)
    1.upto(20).map do |id|
      Customer.new(id, "Customer Group #{id % 4}", rand < 0.5)
    end.each(&block)
  end

  attr_reader :id, :name
  def initialize(id, name, buyer)
    @id = id
    @name = name
    @buyer = buyer
  end

  def buyer?
    @buyer
  end
end

Upvotes: 2

Gokul P
Gokul P

Reputation: 464

Solution:

hsh = {}
Customer.all do |customer|
 if customer.buyer?
    hsh[customer.id] = customer.name
end
puts hsh

Pls, refer the following link to know more about Hash and nested Hash

Upvotes: 0

Related Questions