busfender
busfender

Reputation: 35

Ruby using a date as key in a hash from MySQL

I have a hash which is the result of a .map method on a MySQL2::Result object which looks like this:

{#<Date: 2018-01-02 ((2458121j,0s,0n),+0s,2299161j)>=>"OL,BD,DM,WW,DG"} {#<Date: 2018-01-03 ((2458122j,0s,0n),+0s,2299161j)>=>"KP,LW"} {#<Date: 2018-01-04 ((2458123j,0s,0n),+0s,2299161j)>=>"LW,WW,FS,DG"} {#<Date: 2018-01-05 ((2458124j,0s,0n),+0s,2299161j)>=>"OL,KP,BD,SB,LW,DM,AS,WW,FS,DG"} {#<Date: 2018-01-06 ((2458125j,0s,0n),+0s,2299161j)>=>"OL,KP,BD,SB,LW,DM,AS,WW,FS,DG"}

I would like to pull the values (the two letter items) from the hash, by referencing with the key.

I have tried

puts hash_name["2018-01-06"]
puts hash_name['2018-01-06']
puts hash_name[Date.new(2018,1,6)]
puts hash_name["<Date: 2018-01-06 ((2458125j,0s,0n),+0s,2299161j)>"]
puts hash_name["#<Date: 2018-01-06 ((2458125j,0s,0n),+0s,2299161j)>"]

All return nothing or an error.

The hash is created by doing the following:

hash_name = @available_items.map do
|h| {h["tdate"] => h["items"] }
end

Is there something I can do during the creation of the hash, or now, to be able to easily pull the value out using e.g. can I convert it to some other date format like ISO format?

Thanks

Upvotes: 2

Views: 118

Answers (4)

busfender
busfender

Reputation: 35

In the hopes that this may help others to do a similar thing, here is what I ended up doing.

I have a MySQL2::Result object as shown above, on which I run:

@available_hash = @available_items.map do |row|
[ row["tdate"], row["available"] ]
end.to_h

Having previously declared a start_date and an end_date I then select an available item from the list, at random to fill a new hash using the dates as keys:

$final_hash = Hash.new("")
for date in (start_date..end_date)
@available_today = @available_hash[date].to_s.split(",")
$final_hash[date] = random_item(@available_today)
date +=1;
end

Whilst I am sure there is probably a more elegant way of doing this, I am delighted that you have helped me to get this to work!

Upvotes: 0

tadman
tadman

Reputation: 211690

You're close here, but you're generating an array of hashes, not a singular hash:

hash_name = @available_items.map do |i|
  [ i["tdate"], i["items"] ]
end.to_h

This creates an array of key/value pair arrays, then converts them to a hash with the .to_h method.

You can also use group_by if your input data can be grouped neatly, like:

hash_name = @available_items.group_by do |i|
  i['tdate']
end

Where that approach might be good enough if can deal with the output format. It's keyed by date.

Note that using symbol keys like :tdate and :items is usually preferable to string keys. It's worth trying to steer towards that in most cases where there'd otherwise be rampant repetition of those strings.

Upvotes: 1

mu is too short
mu is too short

Reputation: 434835

I think your problem is that Enumerable#map doesn't do what you think it does. This:

hash_name = @available_items.map do
|h| {h["tdate"] => h["items"] }
end

will give you an array of single entry hashes, the individual hashes will map Dates to strings but the result looks like:

[
  { date1 => string1 },
  { date2 => string2 },
  ...
]

rather than:

{
  date1 => string1,
  date2 => string2,
  ...
}

as you're expecting. Switching to #each_with_object should take care of your problem:

hash_name = @available_items.each_with_object({}) do |row, h|
  h[row['tdate']] = row['items']
end

Upvotes: 2

hagai
hagai

Reputation: 464

Obviously hash map is not suitable for a date as the key, hash map is more suitable for key as id, tag, etc. It should be a unique key.

Please provide more information about what you need to do with this hash map, for sure you can have some more clever data structure.

If you have an array with two keys (tdate, items) and you want to lookup for the date just use select:

result = available_items.select { |elem| elem['tdate'] === Date.new(2001,2,3) }

reference for '===' operator in Date class http://ruby-doc.org/stdlib-2.1.1/libdoc/date/rdoc/Date.html#method-i-3D-3D-3D

Upvotes: -1

Related Questions