2014-02-28 60 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項。