Reputation: 35
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
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
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
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
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