【问题标题】:Grouping a large array of hashes by date ranges按日期范围对大量哈希进行分组
【发布时间】:2014-04-01 22:17:21
【问题描述】:

我有一个大的哈希数组 (~5MB),我需要按滚动日期范围对其进行分组。

这是将数组转换为我正在寻找的滚动数据集的 Ruby 方法:

def rolling(options = {})
  rolling_items = []

  options[:date_range].each do |day|
    start_date = rolling_start_date(day)
    end_date = day

    range = start_date..end_date

    new_items = options[:data].select{|key, value| range.cover? Date.parse(key[:created].to_s)}.uniq { |h| h[:customer] }

    amount = new_items.count


    rolling_items.push({created: day, amount: amount})
  end

  rolling_items
end

这调用了一个rolling_start_date 方法,该方法需要给定的一天并吐出它的开始日期:

def rolling_start_date(end_date)
  old = Time.utc(end_date.year, end_date.month, end_date.day)
  previous = old - 1.month

  if old.day > previous.day
     start_date = previous + 1.day
  else
     start_date = old - 1.month + 1.day
  end

  start_date.to_date
end

我会调用 rolling 方法:rolling(date_range: Date.current.beginning_of_day-1.year..Date.current.end_of_day, data: customers)

这是gist of the huge array 的客户。在上面的调用中用于data

所以rolling 方法然后循环遍历整个date_range 中的每一天并找到它的rolling_start_date,然后在这种情况下找到新日期范围内的哈希值并计算唯一客户并推送它到一个新的rolling_items 数组,所以我最终得到一个如下所示的数组:

[
   {:created=>Fri, 21 Feb 2014, :amount=>2711}, 
   {:created=>Sat, 22 Feb 2014, :amount=>2716}, 
   {:created=>Sun, 23 Feb 2014, :amount=>2720}, 
   {:created=>Mon, 24 Feb 2014, :amount=>2731}, 
   {:created=>Tue, 25 Feb 2014, :amount=>2746}, 
   {:created=>Wed, 26 Feb 2014, :amount=>2761}, 
   {:created=>Thu, 27 Feb 2014, :amount=>2765}, 
   {:created=>Fri, 28 Feb 2014, :amount=>2754}, 
   ...
]

...其中每个哈希是该日期范围内唯一客户的总数。

所以我需要弄清楚如何做仍然是获取每个滚动日期范围的唯一客户数量,而不需要循环 5MB 数组 365 次。

【问题讨论】:

  • 有趣且表述清楚的问题。也许你可以打破new_items = options... 的行以避免需要水平滚动。
  • 我的理解是否正确,{:created=>Fri, 21 Feb 2014, :amount=>2711}, 表示您在上个月左右增加了 2711 个客户?如果是这种情况,是否将每个哈希值改为该日期的客户总数,然后根据需要计算差异以获得滚动值?

标签: ruby arrays hash


【解决方案1】:

也许我不理解其目的,但您能不能只迭代一次 customers 数组,并确定每个客户的天数范围?如果我理解正确,这个范围总是一个月,所以我可以简单地说,在 2013 年 2 月 1 日创建计划的客户 X 将在 2 月 1 日至 2 月 28 日期间的所有日子中添加 1 个唯一客户,对吗?也就是说,鉴于我们还没有计算他(唯一客户),每个客户在所有这些日子里都只是“产生”+1。再说一次,也许我没有正确理解你,但如果我刚才所说的是真的,你可以这样做:

rolling_items = {}

customers.each do |customer|
  start_date = Date.parse(customer[:created])
  end_date = start_date + 30
  (start_date..end_date).each do |date|
    # Add empty Hash with default value 0 if date was not yet in Hash.
    # Add 1 for the customer, so we can see duplicates if we want
    (rolling_items[date] ||= Hash.new(0))[customer[:customer]] += 1
  end
end

rolling_items.each do |date, customers|
  uniq_customers = customers.keys.size # Hash keys are already unique, just count
  puts "\n%s => %s unique customers" % [date.strftime, uniq_customers]
  puts "-" * 20
  customers.each do |customer, times|
    puts "%s => %d" % [customer, times]
  end
end

# 2013-02-28 => 7 unique customers
# --------------------
# cus_05eOKvdnc3MkJO => 2
# cus_0e7LBxIfqSyLAP => 2
# cus_05HVTILpv7CuVS => 2
# cus_1CD4BnX3jDcA3g => 2
# cus_0G9GwU25yAT0ih => 1
# cus_1BqrfANA13SoNc => 3
# cus_0S12vFMb8r6ef1 => 2

# 2013-03-01 ... etc

顺便说一句,那里有很多重复的客户条目具有相同的日期,我不确定这是否是故意的。我拿走了你巨型阵列的前 14 件物品。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 2023-01-28
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 2016-01-09
    • 2013-11-04
    相关资源
    最近更新 更多