简体   繁体   English

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

[英]Lists in python using itertools (moving only 2 items, permutations)

I come from C++ as my 1st programming lenguage, Im just getting into python and im looking for a way to switch numbers from a list, in C++ this would be done using pointers moving them around with loops, however this time I need to generate all the permutations of a list A to a list B in Python我来自 C++ 作为我的第一个编程语言,我刚刚进入 python,我正在寻找一种从列表中切换数字的方法,在 C++ 中,这将使用指针通过循环移动它们来完成,但是这次我需要生成所有Python 中列表 A 到列表 B 的排列

List A (the starter list) and list B (the result list)列表A(起始列表)和列表B(结果列表)

A= 1234
B= 4231

The program has to show all the possible combinations in order, by moving only 2 numbers at he same time until the A list becomes the B list (the following example is simplified to 4 numbers and might not show all the combinations)程序必须按顺序显示所有可能的组合,同时只移动 2 个数字,直到 A 列表变成 B 列表(以下示例简化为 4 个数字,可能不会显示所有组合)

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

In order to acomplish this, I have found the itertools module, that contains a lot of functions, but havent been able to implement to many functions so far, the following code kind of does what its needed however it does not move the numbers in pairs nor in order为了实现这一点,我找到了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)))

Im thinking about adding a while ( A != B ) then stop the permutations, i already tried this but im not familiar with pythons syntax, any help about how can i accomplish this would be appreciated我正在考虑添加一段时间( A != B )然后停止排列,我已经尝试过这个,但我不熟悉 python 语法,关于我如何实现这一点的任何帮助将不胜感激

I am assuming sorting of the input list is not really required , 我假设对输入列表的排序不是必需的,

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)

It's not completely clear what you are asking. 您的要求还不清楚。 I think you are asking for a pythonic way to swap two elements in a list. 我认为您正在要求以Python方式交换列表中的两个元素。 In Python it is usual to separate data structures into immutable and mutable. 在Python中,通常将数据结构分为不可变和可变的。 In this case you could be talking about tuples or lists. 在这种情况下,您可能正在谈论元组或列表。

Let's assume you want to swap elements i and j , with j larger. 假设您要交换元素ij ,其中j较大。

For immutable tuples the pythonic approach will be to generate a new tuple via slicing like this: 对于不可变元组,pythonic方法将通过如下切片生成一个新的元组:

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

For mutable lists it would be pythonic to do much the same as C++, though it's prettier in Python: 对于可变列表,虽然它在Python中更漂亮,但它与python的功能相同,这是pythonic的:

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

Alternatively you could be asking about how to solve your permutation question, in which case the answer is that itertools does not really provide much help. 或者,您可能会询问有关如何解决排列问题的问题,在这种情况下,答案是itertools并没有提供太多帮助。 I would advise depth first search. 我建议深度优先搜索。

On the assumption that you are asking the best way to solve this permutation question - here is a different answer: 假设您正在询问解决此排列问题的最佳方法-这是一个不同的答案:

Think of all the permutations as a set. 将所有排列视为一个集合。 itertools.permutations generates all those permutations in some order. itertools.permutations以某种顺序生成所有这些排列。 That is just what you want if you want to find all or some of those permutations. 如果要查找所有或某些排列,这就是您想要的。 But that's not what you are looking for. 但这不是您想要的。 You are trying to find paths through those permutations. 您正在尝试通过这些排列查找路径 itertools.permutations generates all the permutations in an order but not necessarily the order you want. itertools.permutations生成一个订单的所有排列,但并不一定是你想要的顺序。 And certainly not all the orders: it only generates them once. 当然不是所有的订单:它只会生成一次。

So, you could generate all the permutations and consider them as the nodes of a network. 因此,您可以生成所有排列并将其视为网络的节点。 Then you could link nodes whenever they are connected by a single swap, to get a graph. 然后,只要通过一次交换将节点连接起来,就可以链接它们,以获取图形。 This is called the permutohedron. 这称为排列六面体。 Then you could do a search on that graph to find all the loop-free paths from a to b that you are interested in. This is certainly possible but it's not really optimal. 然后,您可以在该图上进行搜索,以找到您感兴趣的所有从ab的无循环路径。这当然是可能的,但这并不是最佳选择。 Building the whole graph in advance is an unnecessary step since it can easily be generated on demand. 预先构建整个图形是不必要的步骤,因为可以轻松地按需生成它。

Here is some Python code that does just that: it generates a depth first search over the permutohedron by generating the neighbours for a node when needed. 这是一些这样做的Python代码:它会在需要时通过为节点生成邻居来对变面体生成深度优先搜索。 It doesn't use itertools though. 它不使用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)

If you are really interested in using itertools.permutations , then the object you are trying to study is actually: 如果您真的对使用itertools.permutations感兴趣,那么您尝试研究的对象实际上是:

itertools.permutations(itertools.permutations(a))

This generates all possible paths through the set of permutations. 这将生成一系列排列的所有可能路径。 You could work through this rejecting any that don't start at a and that contain steps that are not a single swap. 您可以通过此操作来拒绝所有不以a开头且包含非单次交换步骤的对象。 But that is a very bad approach: this list is very long. 但这是一个非常糟糕的方法:此列表很长。

I guess following is a simpler way, I had nearly same issue (wanted swapped number) in a list (append a copy of list to itself list = list + list and then run :我想以下是一种更简单的方法,我在列表中遇到了几乎相同的问题(想要交换的数字)(将列表的副本附加到自身 list = list + list 然后运行:

from itertools import combinations_with_replacement
mylist = ['a', 'b']    
list(set(combinations_with_replacement(mylist + mylist, r=2)))

results: [('a', 'b'), ('b', 'a'), ('b', 'b'), ('a', 'a')]结果:[('a', 'b'), ('b', 'a'), ('b', 'b'), ('a', 'a')]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM