【问题标题】:How to run a i<j loop in Python, and not repeat (j,i) if (i,j) has already been done?如何在 Python 中运行 i<j 循环,如果 (i,j) 已经完成,则不重复 (j,i)?
【发布时间】:2021-01-11 10:51:18
【问题描述】:

我正在尝试实现一个“i 不等于 j”(i&lt;j) 循环,它会跳过 i = j 的情况,但我还想提出一个额外的要求,即循环不重复(j,i),如果 (i,j) 已经完成(因为由于对称性,这两种情况给出了相同的解决方案)。

第一次尝试

在接下来的代码中,我通过迭代以下列表来创建i&lt;j 循环,其中第二个列表只是前滚的第一个列表 1:

mylist = ['a', 'b', 'c']
np.roll(mylist,2).tolist() = ['b', 'c', 'a']

下面代码生成的序列原来不是我想要的:

import numpy as np

mylist = ['a', 'b', 'c']
for i in mylist:
    for j in np.roll(mylist,2).tolist():
        print(i,j)

因为它返回一个重复的a a 并且有重复的排列a bb a

a b
a c
a a
b b
b c
b a
c b
c c
c a

所需的序列应该是 mylist 中元素的成对组合,因为对于 N=3 元素,应该只有 N*(N-1)/2 = 3 对循环:

a b
a c
b c

【问题讨论】:

  • np.roll 会很好。如果 i 和 j 已经完成,有什么方法可以不重复 j 和 i 的排列? (因为,由于对称性,j 和 i 案例包含与 i 和 j 相同的答案)
  • 你能澄清你到底在问什么吗?是否要旋转列表(将所有元素向上移动,从第一个到最后一个)?你想像旋转一样在列表上进行迭代吗?您真的需要list,还是其他序列类型(例如deque)也合适?
  • 问题显示实际输出。 期望的输出是什么?您在寻找pairwise permutations 吗?
  • 请提供一个实际的预期输出作为打印或列表等。您在这里提到的内容对我来说并不清楚。最好尽量避免主观性。

标签: python list loops combinations permutation


【解决方案1】:

您可以使用一种非常老套的方法来做到这一点,只需删除第一个元素并附加它:

mylist.append(mylist.pop(0))

.append(...) 会将一个元素附加到列表的末尾,.pop(...) 将从给定索引中删除一个元素并返回它。

【讨论】:

    【解决方案2】:

    您可以使用list.insert 来帮助进行左移和右移。

    list.pop,从原始列表中删除元素并返回它。 list.insert 将返回的元素添加到列表中给定索引处(在本例中为 0 或 -1)。注意:这个操作已经到位!

    #Left shift
    mylist = ['apples', 'guitar', 'shirt']
    mylist.insert(-1,mylist.pop(0))
    mylist
    
    ### ['guitar', 'apples', 'shirt']
    
    #Right shift
    mylist = ['apples', 'guitar', 'shirt']
    mylist.insert(0,mylist.pop(-1))
    mylist
    
    ### ['shirt', 'apples', 'guitar']
    

    一个更好的方法是使用collections.deque。这将允许您处理多个班次,并且还可以使用其他一些简洁的队列功能。

    from collections import deque
    
    mylist = ['apples', 'guitar', 'shirt']
    q = deque(mylist)
    q.rotate(1)       # Right shift ['shirt', 'apples', 'guitar']
    q.rotate(-1)      # Left shift ['guitar', 'shirt', 'apples']
    q.rotate(3)       #Right shift of 3 ['apples', 'guitar', 'shirt']
    

    编辑:根据您的 cmets,您正在尝试获得排列 -

    from itertools import product
    [i for i in product(l, repeat=2) if len(set(i))>1]
    
    [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]
    

    out = []
    for i in l:
        for j in l:
            if len(set([i,j]))>1:
                   print(i,j)
    
    a b
    a c
    b a
    b c
    c a
    c b
    

    【讨论】:

    • 抱歉,不要使用itertoolsdeque。只是普通的蟒蛇
    • 但你确实使用 numpy
    • 我使用 numpy 但转换回列表,如果没有办法滚动列表 with 列表。关键不在于只取回可迭代对象。这将是一个包含内部函数的实际循环。我只演示了所需的序列应该是什么
    • 看那是我不确定的部分。对于你不需要滚动的排列。只是元素的叉积。 Itertools 是使用迭代器的基线库(比使用有限的 numpy 更常用)。
    • 你仍然会得到一个列表作为输出。并且对象 jsut 创建了一个迭代器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 2019-04-19
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多