【问题标题】:python: weird list elements combinationpython:奇怪的列表元素组合
【发布时间】:2012-05-18 15:08:23
【问题描述】:

我有以下两个列表:

l1 = [1, 2, ,3]  
l2 = [x, y]  

并且希望所有 5 个元素的列表仅保持 l1 的顺序。说:

[x, y, 1, 2, 3],  
[x, 1, y, 2, 3],  
[x, 1, 2, y, 3],  
[x, 1, 2, 3, y],  
[y, x, 1, 2, 3],  
[y, 1, x, 2, 3],  
[y, 1, 2, x, 3],  
[y, 1, 2, 3, x],  
[1, x, y, 2, 3],  
[1, x, 2, y, 3],  
[1, x, 2, 3, y],  
[1, y, x, 2, 3],  
[1, y, 2, x, 3],  
[1, y, 2, 3, x],  
...  
[1, 2, 3, y, x],  
...  
[1, 2, 3, x, y]  

注意l1 的顺序很重要,l2 不重要。 l2 元素在 l1+l2 位置上运行,但只有 l1 的顺序很重要。 我正在为此苦苦挣扎。任何帮助表示赞赏。

【问题讨论】:

  • @Marcin:我真的不喜欢这个问题;如果人们不知道从哪里开始,为什么他们会问一个问题?有些问题值得回答(“做我的功课”问题),但我不认为这是其中之一。
  • 这不是我的家庭作业。这是对我的问题的过度简化。我处理蛋白质序列比对并陷入困境。无法弄清楚如何处理这个问题的最佳方法。还是谢谢。
  • @ninjagecko (a) 不管是不是作业,这相当于“免费为我编写一些组合代码”(b) 一些代码说明了目标和具体问题是什么。跨度>
  • 尊重!我不赚钱做代码。我是一名物理学家,在结构生物学方面进行一些研究,以开发风湿热疫苗。几个月前我开始使用python,无法处理这个问题。如果你有兴趣,我可以给你一些参考!一切顺利。

标签: python list combinations


【解决方案1】:

我称之为散布 l1 与(l2 的排列)。您可以分两步执行此操作:选择位置,然后排列位置。对于插入点,您可以使用基于掩码的方法 (permutations([True,True,False,False,False])) 或基于索引的方法 (product(*[range(5)]*2))。还没有让后一种技术发挥作用。

from itertools import *

def interspersings(l1,l2):
    for mask in set(permutations([0]*len(l1) + [1]*len(l2))):  # sadly inefficient
        iters = [iter(l1), iter(l2)]
        yield [next(iters[which]) for which in mask]

for perm in permutations(l2):
    for interspersing in interspersings(l1,perm):
        print(interspersing)

演示:

[1, 2, 'x', 'y', 3]
['x', 'y', 1, 2, 3]
[1, 2, 'x', 3, 'y']
[1, 2, 3, 'x', 'y']
['x', 1, 'y', 2, 3]
[1, 'x', 'y', 2, 3]
[1, 'x', 2, 'y', 3]
['x', 1, 2, 'y', 3]
[1, 'x', 2, 3, 'y']
['x', 1, 2, 3, 'y']
[1, 2, 'y', 'x', 3]
['y', 'x', 1, 2, 3]
[1, 2, 'y', 3, 'x']
[1, 2, 3, 'y', 'x']
['y', 1, 'x', 2, 3]
[1, 'y', 'x', 2, 3]
[1, 'y', 2, 'x', 3]
['y', 1, 2, 'x', 3]
[1, 'y', 2, 3, 'x']
['y', 1, 2, 3, 'x']

edit:啊,我提到的后一种技术是由 Mark Longair 在https://stackoverflow.com/a/10655695/711085 正确实现的(它比这种技术效率更高)

【讨论】:

  • 为什么不用itertools.repeat 而不是[0]*[1]*
  • @rubik:可读性,无论如何都必须扩展它们以将调用提供给permutations
  • 问题已解决。非常感谢您的帮助。
  • @ninjagecko:好吧,只需使用chain 将两个重复链接起来就可以了。
  • 我认为您的代码可以通过使用lexicographic permutations 来提高效率。另外,正如我所见,您的代码可能会被用于超过 2 个列表的一般情况(其中一些保留顺序,而另一些则不保留)。而且我看不到 Mark Longair 的答案如何处理超过 2 个列表(尽管在这里我可能对他的方法的可扩展性有误)。
【解决方案2】:

执行此操作的一种方法是使用itertools.combinations 挑选出最终列表的索引,您要将l1 的元素放入其中。然后,对于这些选择中的每一个,使用itertools.permutations 查找第二个列表中项目的所有排列。然后浏览这两个列表,根据索引是应该用于l1l2 的元素,从前面的任何一个列表中挑选出来。

from itertools import combinations, permutations

l1 = [1, 2, 3]
l2 = ["x", "y"]

n = len(l1) + len(l2)

for c in combinations(range(0, n), len(l1)):
    cs = set(c)
    for p in permutations(l2):
        l1i = iter(l1)
        l2i = iter(p)
        print [ l1i.next() if i in cs else l2i.next() for i in range(0,n) ]

输出将是:

[1, 2, 3, 'x', 'y']
[1, 2, 3, 'y', 'x']
[1, 2, 'x', 3, 'y']
[1, 2, 'y', 3, 'x']
[1, 2, 'x', 'y', 3]
[1, 2, 'y', 'x', 3]
[1, 'x', 2, 3, 'y']
[1, 'y', 2, 3, 'x']
[1, 'x', 2, 'y', 3]
[1, 'y', 2, 'x', 3]
[1, 'x', 'y', 2, 3]
[1, 'y', 'x', 2, 3]
['x', 1, 2, 3, 'y']
['y', 1, 2, 3, 'x']
['x', 1, 2, 'y', 3]
['y', 1, 2, 'x', 3]
['x', 1, 'y', 2, 3]
['y', 1, 'x', 2, 3]
['x', 'y', 1, 2, 3]
['y', 'x', 1, 2, 3]

【讨论】:

  • 那么要获得[1, 2, 3]的一致顺序,您只需使用reversed
  • @Darthfett:哎呀,我的意思是 pop(0) 而不是 pop() - 现已修复
  • 我认为reversed 可能会提供更好的性能,因为pop(0) 是O(n),而pop() 是O(1)。鉴于您要从列表中弹出所有项目,它会节省计算(当您在组合排列循环中时这可能很重要)。
  • @Darthfett:好点。不过,我实际上做了一个稍微不同的更改,只是为两者创建迭代器并使用.next(),我希望它更快更清晰。
【解决方案3】:

我认为解决此问题的更好方法之一是保持 [1,2,3] 原样,然后对于“x”,认识到可以插入四个位置(在 '1 ',在'2'之前,......在'3'之后)。然后,一旦插入了“x”,现在有 5 个位置可以插入“y”(未插入“x”的三个位置,加上“x”之前和“x”之后)。使用嵌套循环在每个可能的位置插入“x”和“y”。作为奖励,将嵌套循环提炼成理解......

【讨论】:

    【解决方案4】:

    我尝试使用 l1 和 itertools.permutations 的类占位符,但其中有重复项。

    所以,再试一次,这是我能得到的最简单的方法:

    from itertools import combinations, permutations
    
    l1 = [1, 2, 3]
    l2 = ["x", "y"]
    r = range(len(l1)+len(l2))
    for combo in combinations(r,len(l2)):
      for permu in permutations(l2):
        i1 = iter(l1).next
        i2 = iter(permu).next
        row = [ i2() if i in combo else i1() for i in r ]
        print row
    

    产量:

    ['x', 'y', 1, 2, 3]
    ['y', 'x', 1, 2, 3]
    ['x', 1, 'y', 2, 3]
    ['y', 1, 'x', 2, 3]
    ['x', 1, 2, 'y', 3]
    ['y', 1, 2, 'x', 3]
    ['x', 1, 2, 3, 'y']
    ['y', 1, 2, 3, 'x']
    [1, 'x', 'y', 2, 3]
    [1, 'y', 'x', 2, 3]
    [1, 'x', 2, 'y', 3]
    [1, 'y', 2, 'x', 3]
    [1, 'x', 2, 3, 'y']
    [1, 'y', 2, 3, 'x']
    [1, 2, 'x', 'y', 3]
    [1, 2, 'y', 'x', 3]
    [1, 2, 'x', 3, 'y']
    [1, 2, 'y', 3, 'x']
    [1, 2, 3, 'x', 'y']
    [1, 2, 3, 'y', 'x']
    

    【讨论】:

      【解决方案5】:
      >>> import itertools
      >>> l1 = [1, 2, 3]
      >>> l2 = ['x', 'y', 0, 0, 0]
      >>> l4 = []
      >>> cyc = itertools.cycle(l1)
      >>> for el in set(itertools.permutations(l2, 5)):
      ...     l4.append([cyc.next() if j==0 else j for j in el])
      

      产生:

      >>> l4
      [[1, 2, 'x', 3, 'y'], 
       ['y', 'x', 1, 2, 3], 
       ['x', 1, 'y', 2, 3], 
       ['x', 1, 2, 'y', 3], 
       [1, 2, 3, 'y', 'x'], 
       [1, 'y', 2, 3, 'x'], 
       [1, 2, 3, 'x', 'y'], 
       [1, 'x', 2, 3, 'y'], 
       [1, 'y', 'x', 2, 3], 
       [1, 2, 'x', 'y', 3], 
       [1, 2, 'y', 'x', 3], 
       [1, 'x', 2, 'y', 3], 
       ['y', 1, 2, 'x', 3], 
       ['x', 1, 2, 3, 'y'], 
       [1, 'y', 2, 'x', 3], 
       [1, 'x', 'y', 2, 3], 
       ['y', 1, 2, 3, 'x'], 
       ['x', 'y', 1, 2, 3], 
       [1, 2, 'y', 3, 'x'], 
       ['y', 1, 'x', 2, 3]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-05
        • 1970-01-01
        • 2020-02-07
        • 1970-01-01
        • 1970-01-01
        • 2016-12-19
        • 2012-07-19
        • 1970-01-01
        相关资源
        最近更新 更多