2011-02-11 54 views
0

假設我有一個列表L1,並且L1中的條目有4個部分,格式如下:cat1, cat2, date, ID。該列表按cat1條目按字母順序排列,然後按cat2條目按字母順序排列,然後按最早的date排序。我想要這個列表的子集,其中包含每個cat1, cat2對的最早日期條目。這是代碼,我有一個已經做了這個:選擇列表中最早的條目也滿足其他條件

L1=[A, X, 2008-06-01, 1858 
A, X, 2008-12-05, 1905 
B, X, 2001-08-08, 1149 
B, Y, 2006-03-05, 1638 
B, Y, 2009-06-09, 1950 
C, X, 2005-12-01, 1611 
C, X, 2006-08-08, 1689 
C, X, 2006-11-22, 1712 
C, X, 2008-04-22, 1842 
C, Y, 2008-12-05, 1816 
C, Y, 2008-12-05, 1821 
C, Y, 2008-12-05, 1882 
C, Z, 2008-12-05, 1905 
C, Z, 2009-06-01, 1935 
C, Z, 2009-06-09, 1950 
D, X, 2009-11-06, 1989 
D, Y, 2008-12-05, 1905 
D, Z, 2008-12-05, 1905 
D, Z, 2008-12-05, 1905 
E, X, 2008-12-05, 1905 
E, Z, 2008-12-05, 1905 
F, Y, 2008-12-05, 1905 
G, X, 2008-12-05, 1905 
G, Z, 2007-12-01, 1807] 

L2=[j.next() for i, j in itertools.groupby(L1, lambda x: x.split(",", 2)[:2])] 

L2=[A, X, 2008-06-01, 1858 
B, X, 2001-08-08, 1149 
B, Y, 2006-03-05, 1638 
C, X, 2005-12-01, 1611 
C, Y, 2008-12-05, 1816 
C, Z, 2008-12-05, 1905 
D, X, 2009-11-06, 1989 
D, Y, 2008-12-05, 1905 
D, Z, 2008-12-05, 1905 
E, X, 2008-12-05, 1905 
E, Z, 2008-12-05, 1905 
F, Y, 2008-12-05, 1905 
G, X, 2008-12-05, 1905 
G, Z, 2007-12-01, 1807] 

的訣竅,現在是,我想每個cat1, cat2對,其中ID是值的< = 3個鍵列表中dict1最早進入和dict2。換句話說,一旦找到cat1, cat2對的最早條目,應該在每個dict1dict2中測試,並且如果發現ID包含在每個詞典的4+個鍵的值列表中,則應該轉到下一個對於cat1, cat2對最早的條目,並且爲了將條目添加到L2ID應該在dict1dict2中都在3個或更少的關鍵字中。我不太清楚如何去做這個...也許使用re.search或其他東西?

dict1[key]=[ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID]  
dict2[key]=[ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID] 

因此,而不是隻具有每cat1, cat2對最早進入L2,它將包含最早的條目,其中來自該條目的ID是不是在這兩個dict1dict2ID列表4+鍵中。

+0

你的問題並不完全清楚。你可以發佈一些示例數據嗎? – chmullig 2011-02-11 16:53:05

+0

這是[marsx提出的早期問題]的後續行動(http://stackoverflow.com/questions/4794850/selecting-the-earliest-entry-in-a-list)。 – 2011-02-11 17:04:31

回答

1

如果dict1dict2的值列表不太大,您可以先生成所有有效ID的集合,然後過濾L1以僅包含ID爲的元組(X,Y,日期,ID)設定值ID:

import collections 
def valid_ids(*dcts): 
    valid=collections.defaultdict(int) 
    for dct in dcts: 
     for key,value in dct.iteritems(): 
      valid[value]+=1 
    return set(value for value,count in valid.iteritems() if count<=3) 

ids=valid_ids(dict1,dict2) 

L1_filtered=[text.split(',') for text in L1 if text.split(',')[-1].strip() in ids] 
L2 = [j.next() for i, j in itertools.groupby(L1_filtered, lambda x: x.split(",", 2)[:2])] 

注意,如果dict1dict2具有價值列表與ID的數量巨大,那麼上面的方法是不理想的,因爲你會浪費很多時間來確定該組的在形成L2時,您可能只需要一點點數據。


使用Hugh Bothwell的想法,如果dict1dict2具有較大的價值列表,那麼它可能支付只是檢查是否需要特定的ID是有效的:

def is_valid(ID,*dcts):  
    return sum(1 for dct in dcts 
       for key,value in dct.iteritems() 
       if ID in value) <= 3  

L2=[] 
for key, group in itertools.groupby(L1, lambda x: x.split(",", 2)[:2]): 
    for text in group: 
     X,Y,date,ID = text.split(',') 
     X = X.strip() 
     Y = Y.strip() 
     date = date.strip() 
     ID = ID.strip() 
     if is_valid(ID,dict1,dict2): 
      L2.append(X,Y,date,ID) 
      break 
    else: 
     # There is no valid ID for this group! 
     continue 

注意如果您使用第一種方法,則使用valid_ids,您只需循環一次。如果使用第二種方法,則每個組至少對每個組循環一次字符串(唯一的XY對),並可能多次爲每個組循環。

我的猜測是大多數數據集的第一種方法會更快,但使用真實數據分析這兩種方法可能是最安全的方法。

0

我認爲你需要像

L2 = [] 
for xy,rem in itertools.groupby(L1, lambda x: x.split(",", 2)[:2]): 
    for s in rem: 
     date,id = s.split(",") 
     if TEST_ID(id): 
      L2.append(s) 
      break 
相關問題