如何将MySQL2::Result对象转为以tdate为键items为值的Ruby哈希
解决MySQL2::Result转日期为键的哈希并随机选取元素的问题
嘿,我明白你的需求了——你需要把MySQL2::Result对象转换成以tdate为键、items为值的哈希,还要从每个日期的items列表里随机选元素。之前用pluck出错,大概率是因为pluck是ActiveRecord的方法,MySQL2的结果集不支持,或者直接用pluck转哈希会丢失重复日期的items(后面的覆盖前面的),导致聚合错误。
下面是正确的实现步骤:
1. 构建以tdate为键的哈希
因为MySQL2::Result的每一行是一个类似哈希的对象(键是字符串形式的列名,比如'tdate'),我们可以通过遍历每一行来构建哈希,同时处理同一个日期有多条记录的情况(合并items列表):
基础版遍历
date_items_hash = {} @available_items.each do |row| tdate = row['tdate'] items = row['items'] # 如果当前日期已经在哈希中,就把新的items追加进去(用逗号分隔) if date_items_hash.key?(tdate) date_items_hash[tdate] += ", #{items}" else date_items_hash[tdate] = items end end
简洁版(用each_with_object)
date_items_hash = @available_items.each_with_object({}) do |row, hash| tdate = row['tdate'] items = row['items'] hash[tdate] = hash.key?(tdate) ? "#{hash[tdate]}, #{items}" : items end
2. 从指定日期的items中随机选取元素
拿到哈希后,就可以对指定日期的items字符串进行分割,然后随机选取元素存入新哈希:
处理单个指定日期
random_selections = {} target_date = '2024-05-20' # 替换成你的目标日期 if date_items_hash.key?(target_date) # 分割items字符串,同时去掉每个元素前后的空格(避免多余空格影响) items_list = date_items_hash[target_date].split(',').map(&:strip) # 随机选一个元素存入新哈希 random_selections[target_date] = items_list.sample unless items_list.empty? end
处理所有日期
如果需要给每个日期都随机选一个元素:
random_selections = date_items_hash.each_with_object({}) do |(tdate, items_str), hash| items_list = items_str.split(',').map(&:strip) hash[tdate] = items_list.sample unless items_list.empty? end
为什么之前用pluck会出错?
pluck是ActiveRecord Relation的方法,MySQL2::Result对象本身并不支持这个方法,强行调用会报错。- 即使你把结果集转换成ActiveRecord数组(比如
@available_items.to_a),用pluck(:tdate, :items)得到的是二维数组,再转哈希(比如to_h)时,重复的tdate会被后面的覆盖,导致之前的items丢失,这就是你遇到的“数据聚合错误”。
内容的提问来源于stack exchange,提问作者busfender
相关产品推荐
相关产品推荐

