使用itertools列出python(仅移动2个项目,排列)

时间:2015-09-26 04:56:51

标签: python list permutation

我来自C ++作为我的第一个编程语言,我刚刚进入python并且我正在寻找一种从列表中切换数字的方法,在C ++中这将通过使用指针移动它们来完成循环,但是这次我需要生成列表A的所有排列到Python中的列表B

列表A(起始者列表)和列表B(结果列表)

A= 1234
B= 4231

程序必须按顺序显示所有可能的组合,同时只移动2个数字,直到A列表成为B列表(以下示例简化为4个数字,可能不会显示所有组合)< / p>

[1,2,3,4]
[1,2,4,3]
[1,4,2,3]
[4,1,2,3]
[4,2,1,3]
[4,2,3,1]

为了完成这个,我找到了itertools模块,它包含很多函数,但到目前为止还没有能够实现到很多函数,下面的代码实现了它需要的东西,不过它不会成对或按顺序移动数字

import itertools

from itertools import product, permutations
A = ([1,2,3,4])  
B = ([4,2,3,1])  

print "\n"
print (list(permutations(sorted(B),4)))

我正在考虑添加一段时间(A!= B)然后停止排列,我已经尝试了这个但我不熟悉pythons语法,任何有关如何实现这一点的帮助将不胜感激

3 个答案:

答案 0 :(得分:2)

我假设并不真正需要对输入列表进行排序,

from itertools import permutations
A = ([4, 3, 2, 1])
B = ([1,2,4, 3])

def print_combinations(start, target):
    # use list(permutations(sorted(start), len(start))) if sorting of start is really required
    all_perms = list(permutations(start, len(start)))
    if tuple(target) not in all_perms:
        # return empty list if target is not found in all permutations
        return []
    # return all combinations till target(inclusive)
    # using list slicing
    temp = all_perms[: all_perms.index(tuple(target)) + 1]
    return temp


print print_combinations(A, B)

答案 1 :(得分:1)

你所要求的并不完全清楚。我想你要求一种pythonic方式来交换列表中的两个元素。在Python中,通常将数据结构分为不可变和可变。在这种情况下,您可能会谈论元组或列表。

假设您要交换元素ijj更大。

对于不可变元组,pythonic方法将通过切片生成一个新元组:

next = (current[:i] + current[j:j+1] + current[i+1:j]
                    + current[i:i+1] + current[j+1:])

对于可变列表,与C ++相同的是pythonic,尽管它在Python中更漂亮:

list[i],list[j] = list[j],list[i]

或者你可能会询问如何解决你的排列问题,在这种情况下,答案是itertools并没有提供太多帮助。我会建议深度优先搜索。

答案 2 :(得分:1)

假设您正在询问解决此排列问题的最佳方法 - 这是一个不同的答案:

将所有排列视为一组。 itertools.permutations按某种顺序生成所有这些排列。如果你想找到所有或部分排列,那就是你想要的。但那并不是你想要的。您正试图通过这些排列找到路径itertools.permutations 顺序生成所有排列,但不一定是您想要的顺序。当然不是所有订单:它只生成一次。

因此,您可以生成所有排列并将其视为网络的节点。然后,只要通过单个交换连接节点,就可以链接节点,以获得图形。这被称为permutohedron。然后,您可以在该图表上进行搜索,以找到您感兴趣的从ab的所有无循环路径。这当然是可能的,但它并不是最佳的。提前构建整个图表是一个不必要的步骤,因为它可以很容易地按需生成。

以下是一些Python代码:它通过在需要时为节点生成邻居来生成对permutohedron的深度优先搜索。但它并没有使用itertools

a = (1,2,3,4)
b = (4,2,3,1)

def children(current):
    for i in range(len(a)-1):
        yield (current[:i] + (current[i+1],current[i]) +
                   current[i+2:])

def dfs(current,path,path_as_set):
    path.append(current)
    path_as_set.add(current)
    if current == b:
        yield path
    else:
        for next_perm in children(current):
            if next_perm in path_as_set:
                continue
            for path in dfs(next_perm,path,path_as_set):
                yield path
    path.pop()
    path_as_set.remove(current)

for path in dfs(a,[],set()):
    print(path)

如果您真的对使用itertools.permutations感兴趣,那么您要学习的对象实际上是:

itertools.permutations(itertools.permutations(a))

这将通过一组排列生成所有可能的路径。您可以通过拒绝任何不在a开始且包含非单一交换步骤的拒绝。但这是一个非常糟糕的方法:这个列表很长。