2010-09-01 30 views
10

Listedeki tarihler arasındaki ortalama timedeltayı hesaplamak istiyorum. Aşağıdakiler iyi çalışıyor olsa da, daha akıllı bir yol olup olmadığını merak ediyorum?Ortalama timedelta

delta = lambda last, next: (next - last).seconds + (next - last).days * 86400 
total = sum(delta(items[i-1], items[i]) for i in range(1, len(items))) 
average = total/(len(items) - 1) 
+1

bir tane daha ekleyerek 8640 sonuna kadar iyi bir başlangıç ​​olur;) – aaronasterling

+0

Neden dünya dönme hızını artırmıyorsunuz? ... Sanırım haklısın.) – shinn

cevap

33

Btw, eğer zaman çizelgeleri veya datetimes listesi varsa, neden kendiniz bile matematik yapıyorsunuz?

datetimes = [ ... ] 

# subtracting datetimes gives timedeltas 
timedeltas = [datetimes[i-1]-datetimes[i] for i in range(1, len(datetimes))] 

# giving datetime.timedelta(0) as the start value makes sum work on tds 
average_timedelta = sum(timedeltas, datetime.timedelta(0))/len(timedeltas) 
+3

+1 Çünkü ne OP ne de bunun bir olasılık olduğunu biliyorduk. datetime boku, dizelerden daha sıkıcıdır;) – aaronasterling

+0

Deltasları almak için ortalama ve aaronasterling'leri hesaplamak üzere yolunuza gideceğim. Teşekkürler =) – shinn

+0

Endeksler üzerinde yinelemek çok Pythonic değildir. Ben şöyle giderdim: [a - b için a, b'de b (datetimes [: - 1], datetimes [1:])] ' – abukaj

3

bu deneyin: Bence

from itertools import izip 

def average(items): 
    total = sum((next - last).seconds + (next - last).days * 86400 
       for next, last in izip(items[1:], items)) 
    return total/(len(items) - 1) 

bu daha okunabilir gibi yapıyor. Kodunuzun daha az matematiksel olarak eğimli okuyucuları için bir yorum, her bir deltayı nasıl hesapladığınızı açıklamaya yardımcı olabilir. Buna değer, bir jeneratör ifadesi, baktığım her şeyin en az (ve en azından yavaş olduğunu düşünüyorum) opcode talimatına sahip. Özellikle

# The way in your question compiles to.... 
    3   0 LOAD_CONST    1 (<code object <lambda> at 0xb7760ec0, file 

"scratch.py", line 3>) 
       3 MAKE_FUNCTION   0 
       6 STORE_DEREF    1 (delta) 

    4   9 LOAD_GLOBAL    0 (sum) 
      12 LOAD_CLOSURE    0 (items) 
      15 LOAD_CLOSURE    1 (delta) 
      18 BUILD_TUPLE    2 
      21 LOAD_CONST    2 (<code object <genexpr> at 0xb77c0a40, file "scratch.py", line 4>) 
      24 MAKE_CLOSURE    0 
      27 LOAD_GLOBAL    1 (range) 
      30 LOAD_CONST    3 (1) 
      33 LOAD_GLOBAL    2 (len) 
      36 LOAD_DEREF    0 (items) 
      39 CALL_FUNCTION   1 
      42 CALL_FUNCTION   2 
      45 GET_ITER    
      46 CALL_FUNCTION   1 
      49 CALL_FUNCTION   1 
      52 STORE_FAST    1 (total) 

    5   55 LOAD_FAST    1 (total) 
      58 LOAD_GLOBAL    2 (len) 
      61 LOAD_DEREF    0 (items) 
      64 CALL_FUNCTION   1 
      67 LOAD_CONST    3 (1) 
      70 BINARY_SUBTRACT  
      71 BINARY_DIVIDE  
      72 STORE_FAST    2 (average) 
      75 LOAD_CONST    0 (None) 
      78 RETURN_VALUE   
None 
# 
#doing it with just one generator expression and itertools... 

    4   0 LOAD_GLOBAL    0 (sum) 
       3 LOAD_CONST    1 (<code object <genexpr> at 0xb777eec0, file "scratch.py", line 4>) 
       6 MAKE_FUNCTION   0 

    5   9 LOAD_GLOBAL    1 (izip) 
      12 LOAD_FAST    0 (items) 
      15 LOAD_CONST    2 (1) 
      18 SLICE+1    
      19 LOAD_FAST    0 (items) 
      22 CALL_FUNCTION   2 
      25 GET_ITER    
      26 CALL_FUNCTION   1 
      29 CALL_FUNCTION   1 
      32 STORE_FAST    1 (total) 

    6   35 LOAD_FAST    1 (total) 
      38 LOAD_GLOBAL    2 (len) 
      41 LOAD_FAST    0 (items) 
      44 CALL_FUNCTION   1 
      47 LOAD_CONST    2 (1) 
      50 BINARY_SUBTRACT  
      51 BINARY_DIVIDE  
      52 RETURN_VALUE   
None 

, lambda bırakarak bize bir demet bina ve iki kapanışları yüklenirken, bir kapatma yapmaktan kaçınmaya olanak verir. Beş fonksiyon her iki şekilde denir. Tabii ki, bu tür bir performansla ilgili endişeler çok saçma ama kaputun altında neler olduğunu bilmek güzel. En önemli şey okunabilirlik ve bence bu şekilde yapmanın da bu konuda yüksek puanlar aldığını düşünüyorum.

+0

Evet, bu daha iyi. Teşekkürler! – shinn

+0

@shinn, THC4k'nin cevabını kabul ederseniz, bunu silebilirim. – aaronasterling

+0

Silmemelisiniz. İzip ile yolu seviyorum. – shinn