【问题标题】:Ruby using a date as key in a hash from MySQLRuby 使用日期作为 MySQL 哈希中的键
【发布时间】:2018-06-17 16:00:51
【问题描述】:

我有一个哈希,它是 MySQL2::Result 对象上 .map 方法的结果,如下所示:

{#<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"}

我想通过键引用从哈希中提取值(两个字母项)。

我试过了

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)>"]

全部不返回任何内容或错误。

通过执行以下操作创建哈希:

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

在创建哈希期间或现在我可以做些什么,以便能够使用例如轻松提取值我可以将其转换为其他日期格式,例如 ISO 格式吗?

谢谢

【问题讨论】:

    标签: mysql ruby date hash


    【解决方案1】:

    我认为你的问题是Enumerable#map 没有做你认为它做的事情。这个:

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

    会给你一个单条目哈希的array,各个哈希会将日期映射到字符串,但结果如下所示:

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

    而不是:

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

    如您所愿。切换到#each_with_object 应该可以解决您的问题:

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

    【讨论】:

    • @tadman 有时,但有时我更喜欢 each_with_object 的异端邪说:)
    • 从技术上讲,它产生的垃圾更少,但奇怪的是它并不总是表现得更好。 Ruby 在内部是一个奇怪的东西。
    【解决方案2】:

    你在这里很接近,但你正在生成一个哈希数组,而不是一个单一的哈希:

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

    这会创建一个键/值对数组的数组,然后使用.to_h 方法将它们转换为哈希。

    如果您的输入数据可以整齐地分组,您也可以使用group_by,例如:

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

    如果可以处理输出格式,这种方法可能就足够了。它是按日期键入的。

    请注意,使用 :tdate:items 等符号键通常比字符串键更可取。在大多数情况下,如果这些字符串会大量重复出现,那么值得尝试将其引导。

    【讨论】:

    • 谢谢。您能进一步解释一下符号键吗?我了解符号的一般概念,但不确定在这种情况下如何工作。您是否建议每个tdate(例如“2018-01-06”)都应该变成:2018-01-06
    • 我并不是建议日期本身成为符号,那样会很混乱,而是存储日期的关键是,或者:tdate,而不是'tdate'。 Ruby 1.9+ 的哈希声明风格,语法上类似于 JavaScript,默认使用:{ tdate: '2018-01-06' } 等价于 { :tdate =&gt; '2018-01-06' }
    【解决方案3】:

    希望这可以帮助其他人做类似的事情,这就是我最终做的事情。

    我有一个 MySQL2::Result 对象,如上所示,我在其上运行:

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

    之前声明了start_dateend_date,然后我从列表中选择一个可用的项目,使用日期作为键随机填充一个新的哈希:

    $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
    

    虽然我确信可能有更优雅的方式来做这件事,但我很高兴你帮助我让它工作!

    【讨论】:

      【解决方案4】:

      显然hash map不适合以日期为key,hash map更适合id、tag等key,应该是唯一的key。

      请提供更多关于您需要使用此哈希映射做什么的信息,以确保您可以拥有一些更聪明的数据结构。

      如果您有一个包含两个键(tdate、items)的数组,并且您想查找日期,只需使用 select:

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

      日期类中“===”运算符的参考 http://ruby-doc.org/stdlib-2.1.1/libdoc/date/rdoc/Date.html#method-i-3D-3D-3D

      【讨论】:

        猜你喜欢
        • 2011-07-01
        • 2018-06-30
        • 1970-01-01
        • 2017-03-23
        • 1970-01-01
        • 2018-02-19
        • 2020-06-20
        • 2020-07-02
        • 1970-01-01
        相关资源
        最近更新 更多