【问题标题】:python iterating multiple lists in multiple loopspython在多个循环中迭代多个列表
【发布时间】:2014-01-13 00:31:18
【问题描述】:

我需要遍历多个列表,并对匹配的记录做一些计算:

for (a,b,c,d) in list1:
   for (a2,b2,e) in list2:
       if (a==a2) and (b==b2):
           mylist.add(a,b,c,d,e,d*e)

是否有一种有效的方法来进行上述计算。非常感谢。

【问题讨论】:

  • 给我们举个例子看看列表是什么样子的?
  • 首先,在外循环中` If a != b: continue`
  • @ColBeseder:我猜意图是 if (a==a2) and (b==b2),但我同意 OP 应该澄清一下。
  • 列表可能看起来像 list1 = (name, last_name, gender, job_class, Salary) list2 = (name, last_name, increase) 并假设还有一个列表 list3 = (job_class, bonus) 所以需要找到所有匹配的记录,这样
  • 您似乎使用了错误的数据结构来完成这项工作。请展示一些实际代码和一些实际数据。

标签: python list loops


【解决方案1】:

构建一些字典以便快速查找:

data1 = {(a, b): (c, d) for a, b, c, d in list1}
data2 = {(a, b): e for a, b, e in list2}

result = []
for a, b in set(data1) & set(data2):
    c, d = data1[a, b]
    e = data2[a, b]
    result.append((a, b, c, d, e, e*d))

【讨论】:

  • 值得指出,这比问题中数千个数据集的实现要慢。
  • @adsmith:真的吗?这不应该是 O(N) vs O(N^2) 吗?
  • @adsmith:我觉得这很难相信。我可以相信对于非常小的列表来说它会比较慢,但是对于中等大小的列表,我认为这里的算法复杂性必须获胜。 @Eric:请注意,这假定 (a,b) 中的所有内容都是唯一的;并非不合理,但我从这个问题中不清楚。 (不确定 OP 如何处理两个同名的人,例如)
  • 我为list1 生成了2000 个条目的虚拟列表,为list2 生成了1000 个条目。有很多重复的条目,所以这可能是导致效率下降的原因。使用实际数据,字典可能会提供更快的查找,但如果没有一些真实数据就更难测试,而且我不打算生成 2,000 个大项目的虚拟数据来运行timeit
【解决方案2】:

牢记新信息,即:

  1. list1 的元素格式为(name, last_name, gender, job_class, salary)
  2. list2 包含 (name, last_name, increase) 形式的元素(可能是对人的加薪),
  3. list3 具有 (job_class, bonus) 等元素,

...使用dict,您可能会在性能和代码清晰度方面受益。

使用 (first,last) 形式的元组来引用程序中的每个人,您可以执行以下操作(在使用 input 获取信息的基本示例中):

people = dict()
for i in range(num_ppl):
    name = tuple(input().split()) # input is something like "Bob Smith"
    people[name] = getPeopleInfo() # read gender, job_class, salary, etc. and make a list
for i in range(num_raises):
    first, last, increase = input().split()
    people[(first,last)][-1] *= float(increase)
for i in range(num_bonuses):
    job_class, bonus = input().split()
    for name in people: # iterating through a dict gives the keys (similar to indices of a list, but can be immutable types such as tuples)
        if people[name][2] == job_class:
            people[name][-1] += bonus

strinttuple 等任何不可变类型都可以用作dict 中的键,类似于用于list 的基于0 的整数。请注意,list 可以更改(例如使用list.append)并且是“可变的”;因此 list 不能是键。有关dict 的更多信息,您可以阅读documentation

【讨论】:

    【解决方案3】:

    就时间和内存效率而言,当前的代码似乎大多是最优的。您必须相互检查 list1list2 的所有元素以进行比较。
    消除一些重复“错误”情况的一种补充方法是在两个 for 循环行之间添加:

    if a != b: # none of the items in list2 will satisfy a==b2 and b==b2
        continue
    

    您也可以在 Python 中使用 if a == b == b2,而不必将语句与 and 绑定在一起。

    根据您的记录的存储和访问方式,您可能会从使用dicts 而不是lists 中受益。 dict 可以判断是否有其实现的示例可能是:

    lookup = dict()
    
    # when adding an item to what would be list2
    if b2 in not in lookup:
        lookup[b2] = []
    lookup[b2].append((a2,e))
    # ...
    
    for (a,b,c,d) in list1:
        if a == b and a in lookup:
            for (a2,e) in lookup[a]:
                mylist.add(a,b,c,d,e,d*e)
    

    【讨论】:

    • 小心,应该是if a==a2 and b==b2:- 问题中有错字,但cmets 说清楚了。
    • 列表可能看起来像 list1 = (name, last_name, gender, job_class, Salary) list2 = (name, last_name, increase) 并假设还有一个列表 list3 = (job_class, bonus) 所以需要找到所有匹配的记录,这样 for (name, last_name, gender, job_class1, Salary) in list1: for (name2, last_name2, increase) in list 2: if (name==name2) and (last_name==last_name2): for (job_class2, bonus) in list3: if(job_class==job_class2): final_list.add(name, last_name, Salary*increase + bonus)
    猜你喜欢
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    相关资源
    最近更新 更多