0

我有两个大清单。它们中的每一个都由列表组成:

list_1 = [[1, "BMW", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "BMW", "Boston", "01Jan2013"],...]

list_2 = [[1, "Mercedes", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "Toyota", "Boston", "01Jan2013"],...]

内部列表始终具有相同的项目类型。

现在我想使用内部列表的第 1 项、第 3 项和第 4 项将每个内部 inlist_1与一个 in匹配list_2。即:序列号、城市起源和日期。这些键始终与 list_2 相同。中的内部列表list_1只能有 0 或 1 个匹配项list_2

最pythonic和最快的方法是什么?我应该将列表转换为字典吗?

4

5 回答 5

3

假设list_1不能包含重复项(根据您的评论),您可以将其转换为 a setof tuples 而不是列表列表。这样,您可以使用in运算符有效地检查某个项目是否在集合中。

您需要使用元组而不是列表,因为列表是可变的(因此不可散列),因此不能将它们放入set. 如果您使用 a ,这同样适用dict,但 aset似乎更适合您的用例(不清楚您将使用什么作为 的键dict)。

于 2013-01-26T21:45:31.580 回答
2

在速度方面,您可能想要使用字典。似乎以一种或另一种方式,您将需要遍历一个列表。字典当然比遍历一个列表要快,所以你可以将至少一个列表变成一个字典。(我在两个单独的列表中测试了以下解决方案,其中包含 200,000 个条目,就像你的一样,我的速度平均为 0.109999 秒。列表远远超出了这个标记。)如果你只是尝试使用列表,你可能不会接近那个或元组,除非您的条目顺序允许您使用 zip 之类的东西。您的序列号似乎是唯一的,因此以下方法可行(通过迭代一个列表,然后将项目 1、3 和 4 [在位置 0、2 和 3] 与字典中的值进行比较):

list_1 = [[1, "BMW", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "BMW", "Boston", "01Jan2013"]]

list_2 = [[1, "Mercedes", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "Toyota", "Boston", "01Jan2013"]]


dict_2 = dict()

for elem in list_2:
    dict_2[elem[0]] = elem[1:]

for item in list_1:
    if dict_2[item[0]][1:] == item[2:]:    # Have to offset the index since dict list only has three elements
        print item


[1, 'BMW', 'Boston', '01Jan2013']
[37, 'Chevrolet', 'Denver', '05Jan2013']
[854, 'BMW', 'Boston', '01Jan2013']

将第二个列表转换为字典后,您只需遍历一个列表即可获得结果。此解决方案将从您似乎想要的 list_1 返回每个匹配项的整个子列表。如果您想要两个列表中的完整匹配子列表,这将起作用:

for item in list_1:
    if dict_2[item[0]][1:] == item[2:]:
        print item, [item[0]] + dict_2[item[0]]


[1, 'BMW', 'Boston', '01Jan2013'] [1, 'Mercedes', 'Boston', '01Jan2013']
[37, 'Chevrolet', 'Denver', '05Jan2013'] [37, 'Chevrolet', 'Denver', '05Jan2013']
[854, 'BMW', 'Boston', '01Jan2013'] [854, 'Toyota', 'Boston', '01Jan2013']
于 2013-01-26T21:33:18.000 回答
1

类似于@omz 的解决方案是将列表转换为字典。dict 键是元组(serial,city,date)(项目 1、3 和 4),值是另一个字段“make”(项目 2)。然后要匹配它们,只需遍历list_1(now dict_1) 的键,尝试检索 的相应成员dict_2

dict_1 = {(1, "Boston", "01Jan2013"):"BMW", (37, "Denver", "05Jan2013"):"Chevrolet", (854, "Boston", "01Jan2013"):"BMW",...}

dict_2 = {(1, "Boston", "01Jan2013"):"Mercedes", (37, "Denver", "05Jan2013"):"Chevrolet", (854, "Boston", "01Jan2013"):"Toyota",...}

for k in dict_1:
    match = dict_2.get (k, None)
    if match is not None:
        print "Match found:", match
    else:
        print "No match"

自然,当你找到匹配项时你会做什么不会是我写的,但这应该有助于展示你如何找到匹配项。

于 2013-01-26T22:00:56.863 回答
1

您可以定义一个键函数,指定要比较的字段:

def item_key(item):
    return tuple(item[i] for i in [0, 2, 3])

它应该是可散列的,以便您可以将其用作 dict 键。您可以创建从项目键到项目本身的映射,或者如果不同项目可以共享相同的键,则创建项目列表。

key_to_item2 = dict((item_key(item), item) for item in list2)

现在您可以根据字典测试list1中的每个项目。

for item1 in list1:
    item2 = key_to_item2.get(item_key(item1))
    if item2 is None:
        # no match found
    else:
        # item2 in list2 matches item1 in list1

这种方法可以很容易地调整为使用其他字段进行匹配和支持多个匹配。

于 2013-01-26T21:27:49.473 回答
1

什么是“最佳”解决方案取决于您想要什么。如果是关于速度,那么根据您输入的大小,字典可能是最好的主意。

如果它是关于清晰和简洁,我认为保留列表并执行以下操作是非常pythonic:

result = []
for l1 in list1:
    result.append([l2 for l2 in list2
                   if l1[0] == l2[0] and l1[2] == l2[2] and l1[3] == l2[3]])
    assert(len(result[-1]) in [0,1])
于 2013-01-26T21:44:03.527 回答