【问题标题】:Iterate over (item, others) in a list迭代列表中的(项目,其他)
【发布时间】:2012-08-31 20:22:21
【问题描述】:

假设我有一个列表:

l = [0, 1, 2, 3]

如何遍历列表,从列表中获取每个项目及其补充项?也就是说,

for item, others in ...
    print(item, others)

会打印

0 [1, 2, 3]
1 [0, 2, 3]
2 [0, 1, 3]
3 [0, 1, 2]

理想情况下,我正在寻找可以在理解中使用的简洁表达式。

【问题讨论】:

    标签: python sequence itertools complement


    【解决方案1】:

    这很容易理解:

    for index, item in enumerate(l):
        others = l[:index] + l[index+1:]
    

    如果你坚持,你可以制作一个迭代器:

    def iter_with_others(l):
        for index, item in enumerate(l):
            yield item, l[:index] + l[index+1:]
    

    给出它的用法:

    for item, others in iter_with_others(l):
        print(item, others)
    

    【讨论】:

    • 这很好用,这正是 ecatmur 所要求的,但似乎是无偿创建列表的练习。对于较大的列表,它的性能可能会很差。我想知道创建某种提供原始列表视图的包装器对象是否会更好。
    • @StevenRumbalski:是的,但除非有巨大的需求,否则我会将其作为练习留给读者。
    【解决方案2】:

    回答我自己的问题,可以使用itertools.combinations,利用结果按字典顺序发出的事实:

    from itertools import combinations
    zip(l, combinations(reversed(l), len(l) - 1))
    

    但是,这相当模糊; nightcracker 的解决方案很多对于读者来说更容易理解!

    【讨论】:

      【解决方案3】:

      怎么样

      >>> [(i, [j for j in L if j != i]) for i in L]
      [(0, [1, 2, 3]), (1, [0, 2, 3]), (2, [0, 1, 3]), (3, [0, 1, 2])]
      

      好的,这是大量的测试,@nightcracker 的解决方案可能更有效,但是呃...

      【讨论】:

      • 您可以使用生成器表达式而不是列表推导式,从而避免像@StevenRumbalski 所梦想的那样创建不必要的列表。
      • 是的,我可以为整个表达式使用生成器,但不能用于内部循环:OP 想要打印列表,而不是生成器..
      • 是的,至少在他的例子中是这样。问题是这是否真的是他想要对结果做的事情。但他可以自己决定。
      猜你喜欢
      • 2020-03-17
      • 1970-01-01
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      • 2014-10-26
      • 2021-03-12
      • 2020-05-27
      相关资源
      最近更新 更多