2014-02-28 61 views
1

我有一个大型数组(〜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次。

+0

有趣和明确的问题。也许你可以打破'new_items = options ...'这一行来避免水平滚动的需要。 –

+0

我的理解是否正确:'{:created => Fri,2014年2月21日,:amount => 2711},'是否表示您在前一个月左右添加了2711个客户?如果是这样的话,那么如何让每个散列代替当时的客户总数,然后根据需要计算差异来获得滚动值? –

回答

0

也许我不明白目的,但是您是否可以不重复customers阵列一次,并确定每个客户的日期范围?如果我理解正确,这个范围总是一个月,所以我可以简单地说,拥有2013年2月1日创建的计划的客户X将在2月1日到2月28日之间的所有日子中增加一个独特客户,对吗?也就是说,所有这些日子里,每个客户都只是“生成”+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项。