我有两个大清单。每个都包含列表:
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项,将list_1
中的每个内部与list_2
中的内部匹配。即:序列号,城市来源和日期。这些键始终与list_2相同。 list_1
中的内部列表在list_2
中只能有0或1个匹配。
什么是最pythonic和最快的方法?我应该将列表转换为字典吗?
答案 0 :(得分:3)
假设list_1
不能包含重复项(根据您的评论),您可以将其转换为set
tuple
而不是列表。这样,您可以使用in
运算符有效地检查某个项目是否在集合中。
您需要使用元组而不是列表,因为列表是可变的(因此不可清除),因此无法将它们放入set
。如果您使用dict
,则同样适用,但set
似乎更适合您的用例(不清楚您使用什么作为dict
的关键字)
答案 1 :(得分: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']
答案 2 :(得分: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
可以轻松调整此方法,以便使用其他字段进行匹配和支持多个匹配。
答案 3 :(得分: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])
答案 4 :(得分:1)
类似于@omz的解决方案是将列表转换为字典。 dict键是元组(serial,city,date)
(第1,3和4项),值将是另一个字段'make'(第2项)。然后匹配它们,只需遍历list_1
(现在为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"
当然,当你找到匹配时你所做的不是我写的,但这应该用来展示你如何找到匹配。