2011-02-11 63 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 
相关问题