在列表列表中比较子列表的有效方法?

时间:2013-05-21 11:48:03

标签: python algorithm

对于标题的错误措辞感到抱歉(如果没有找借口,谷歌搜索失败......)。希望解释清楚。

我有两个列表列表(从现在开始的行),我想根据一些标准检查列表中两条线相互匹配的情况。 我知道的唯一方法是在双循环中进行,这很慢。首先排序它们(列表)不是一个选项,因为列表彼此不完全一致。

修改

好的,这是两个列表的样子。它们长约10,000个子列表;我尽力模仿他们的特点和彼此的关系(不同的长度,大多数子列表在其他列表中有匹配(按日期和2个大写元素),但有些不在下面。

['xyz', 'xyz', '12/11/2006', 'Zatgxg', 'Fuietg', '3'],  
['xyz', 'xyz', '23/04/2011', 'Gcatia', 'Cecfoz', '0'],  
['xyz', 'xyz', '08/03/2003', 'Fuietg', 'Erzhgg', '2'],  
['xyz', 'xyz', '07/05/2006', 'Aapoaa', 'Fuietg', '1'],  
['xyz', 'xyz', '15/05/2004', 'Bfaext', 'Eghege', '1'],   
['xyz', 'xyz', '05/02/2006', 'Gtoadr', 'Udpfdf', '1'],  
['xyz', 'xyz', '11/09/2004', 'Racdgo', 'Zchxgx', '0'],  
['xyz', 'xyz', '03/04/2011', 'Zdcfii', 'Rhiiog', '1'],  
['xyz', 'xyz', '07/04/2007', 'Dabzgi', 'Gpeiot', '4'],  
['xyz', 'xyz', '16/03/2008', 'Dohbur', 'Oucegh', '2']
##################

['xyz', 'xyz', 'Dohbur', 'Oucegh', 'xyz', 'xyz', '16/03/2008'],  
['xyz', 'xyz', 'Dabzgi', 'Gpeiot', 'xyz', 'xyz', '07/04/2007'],  
['xyz', 'xyz', 'Fuietg', 'Erzhgg', 'xyz', 'xyz', '08/03/2003'],  
['xyz', 'xyz', 'Udioac', 'Gceabb', 'xyz', 'xyz', '21/02/2004'],  
['xyz', 'xyz', 'Bfaext', 'Eghege', 'xyz', 'xyz', '15/05/2004'],  
['xyz', 'xyz', 'Racdgo', 'Zchxgx', 'xyz', 'xyz', '11/09/2004'],  
['xyz', 'xyz', 'Gtoadr', 'Udpfdf', 'xyz', 'xyz', '05/02/2006'],  
['xyz', 'xyz', 'Aapoaa', 'Fuietg', 'xyz', 'xyz', '07/05/2006']

3 个答案:

答案 0 :(得分:1)

从你的问题中,我收集到你有2个相同大小的名单,并以某种方式订购,不得改变。

您想知道列表B中是否存在列表A中的项目。

您可以进行排序以保持对初始索引的引用,这样您就可以更快地使用bisect进行搜索。

请参阅How to get indices of a sorted array in Python

numpy.argsort也是这样做的

修改

根据你的评论,一个简单的解决方案是(见Common elements comparison between 2 lists

>>> list1 = [1,2,3,4,5,6]
>>> list2 = [3, 5, 7, 9]
>>> list(set(list1).intersection(list2))
[3, 5]

我想指出,这是非常高效的,因为测试和插入集合中的O(1)操作,使整个操作O(n+m)

(在示例中,列表已排序,但这只是巧合)

更多编辑,基于示例

如果您只需要匹配的元素,可以使用前一个的简单修订:

list(set([x[0:4] for x in list1]).intersection([(x[0], x[1], x[2], x[3], x[6]) for x in list2]))

理解会将list1和list2减少为预期顺序中的公共元素。如果你需要两个列表中的所有元素,它可能会更复杂。

答案 1 :(得分:0)

创建一个哈希函数,当字符串的条件匹配时,哈希值匹配。

然后将一组列表插入到具有该哈希的哈希表中,并使用相同的哈希查找字符串。

E.g。假设你需要匹配第1列和第2列,一起创建1和2的哈希值。

答案 2 :(得分:0)

您需要规范化每个矩阵中的线条,然后您可以使用规范化值的集合交集来给出匹配。定义anorm和bnorm函数以从列表中生成一个元组,该列表将匹配匹配的行。如果多行匹配,那么代码也应该处理它。

>>> alist = [['xyz', 'xyz', '12/11/2006', 'Zatgxg', 'Fuietg', '3'],  
['xyz', 'xyz', '23/04/2011', 'Gcatia', 'Cecfoz', '0'],  
['xyz', 'xyz', '08/03/2003', 'Fuietg', 'Erzhgg', '2'],  
['xyz', 'xyz', '07/05/2006', 'Aapoaa', 'Fuietg', '1'],  
['xyz', 'xyz', '15/05/2004', 'Bfaext', 'Eghege', '1'],   
['xyz', 'xyz', '05/02/2006', 'Gtoadr', 'Udpfdf', '1'],  
['xyz', 'xyz', '11/09/2004', 'Racdgo', 'Zchxgx', '0'],  
['xyz', 'xyz', '03/04/2011', 'Zdcfii', 'Rhiiog', '1'],  
['xyz', 'xyz', '07/04/2007', 'Dabzgi', 'Gpeiot', '4'],  
['xyz', 'xyz', '16/03/2008', 'Dohbur', 'Oucegh', '2']]
>>> blist = [['xyz', 'xyz', 'Dohbur', 'Oucegh', 'xyz', 'xyz', '16/03/2008'],  
['xyz', 'xyz', 'Dabzgi', 'Gpeiot', 'xyz', 'xyz', '07/04/2007'],  
['xyz', 'xyz', 'Fuietg', 'Erzhgg', 'xyz', 'xyz', '08/03/2003'],  
['xyz', 'xyz', 'Udioac', 'Gceabb', 'xyz', 'xyz', '21/02/2004'],  
['xyz', 'xyz', 'Bfaext', 'Eghege', 'xyz', 'xyz', '15/05/2004'],  
['xyz', 'xyz', 'Racdgo', 'Zchxgx', 'xyz', 'xyz', '11/09/2004'],  
['xyz', 'xyz', 'Gtoadr', 'Udpfdf', 'xyz', 'xyz', '05/02/2006'],  
['xyz', 'xyz', 'Aapoaa', 'Fuietg', 'xyz', 'xyz', '07/05/2006']]
>>> from collections import defaultdict
>>> def anorm(line): return (line[0], line[2], line[4].upper())

>>> def bnorm(line): return (line[1], line[6], line[3].upper())

>>> def fitting(a, b, an, bn):
    anormalized, bnormalized = defaultdict(list), defaultdict(list)
    for i, line in enumerate(a):
        anormalized[an(line)].append(i)
    for i, line in enumerate(b):
        bnormalized[bn(line)].append(i)
    common = set(anormalized).intersection(set(bnormalized))
    for norm in common:
        print('lines at indices %r of a and %r of b are common'
              % (anormalized[norm], bnormalized[norm]))


>>> fitting(alist, blist, anorm, bnorm)
lines at indices [3] of a and [7] of b are common
lines at indices [5] of a and [6] of b are common
lines at indices [2] of a and [2] of b are common
lines at indices [9] of a and [0] of b are common
lines at indices [8] of a and [1] of b are common
lines at indices [6] of a and [5] of b are common
lines at indices [4] of a and [4] of b are common
>>>