简体   繁体   English

生成2d数组的所有唯一排列

[英]Generate all unique permutations of 2d array

I would like to be able to generate all unique permutations of a 2d array in python. 我希望能够在python中生成二维数组的所有唯一排列。

For example take this 2d array [[1,1],[0,0]] I would like back 例如,我想回到这个2d数组[[1,1],[0,0]]

[[0,0],
[1,1]]

[[0,1],
[0,1]]

[[0,1]
[1,0]]

[[1,0]
[0,1]]

[[1,0]
[1,0]]

[[1,1]
[0,0]]

You can do it like this 你可以这样做

d = [[1, 1], [0, 0]]
from itertools import permutations, chain
from pprint import pprint
pprint(sorted([i[:2], i[2:]] for i in set(permutations(chain.from_iterable(d)))))

Output 产量

[[[0, 0], [1, 1]],
 [[0, 1], [0, 1]],
 [[0, 1], [1, 0]],
 [[1, 0], [0, 1]],
 [[1, 0], [1, 0]],
 [[1, 1], [0, 0]]]

Is this the approximate size of your array? 这是您阵列的大致尺寸吗? If it's huge, this solution will be mightily slow, but will work eventually. 如果它很大,这个解决方案将会非常缓慢,但最终会有效。 For arrays of this size, python's built in itertools are the way to go, plus some numpy manipulation. 对于这种大小的数组,python内置的itertools是可行的方法,加上一些numpy操作。

Additionally, the number of unique permutations depends on the number of elements in your initial array that are different. 此外,唯一排列的数量取决于初始数组中不同的元素数。 So flattening the array, producing all the permutations, reshaping into 2x2 (or your desired size), and comparing will get you the "unique" arrays, as you seem to mean it. 因此扁平化阵列,产生所有排列,重新塑造成2x2(或您想要的大小),并且比较将获得“独特”阵列,正如您所说的那样。

I've used loops here (rather than comprehensions) to make things easy to read/test/check. 我在这里使用循环(而不是理解)来使事情易于阅读/测试/检查。 Definitely translate to comprehensions (faster, all around better) before you use for real. 在用于真实之前,绝对可以转化为理解(更快,更好)。

a = np.array([[1,1],[0,0]]).flatten()
permutes = []
for i in permutations(a):
    permutes.append((np.array(i).reshape((2,2))))

unique_permutes = [permutes[0]]
for i in permutes[1:]:
    one_equal = False
    for unique in unique_permutes:
        if np.array_equal(i, unique):
            one_equal = True
            break
    if not one_equal:
        unique_permutes.append(i)

print len(unique_permutes) #same as what you wanted
for i in unique_permutes: #prints pretilly for sanity checking
    print i

One -- not particularly efficient -- way to do it would be something like 一个 - 不是特别有效 - 这样做的方式就像是

from itertools import permutations, chain, islice

def uniperm_arrays(arr):
    flat = chain.from_iterable(arr)
    perms = set(permutations(flat))
    for perm in perms:
        pit = iter(perm)
        yield [list(islice(pit, len(row))) for row in arr]

which gives 这使

>>> uu = uniperm_arrays([[1,1],[0,0]])
>>> for u in uu:
...     for row in u:
...         print(row)
...     print()
...     
[1, 0]
[1, 0]

[1, 1]
[0, 0]

[0, 0]
[1, 1]

[1, 0]
[0, 1]

[0, 1]
[1, 0]

[0, 1]
[0, 1]

EDIT this should work on 2d arrays of any dimension and shape. 编辑这应该适用于任何尺寸和形状的2d阵列。

Based on the idea that the permutations are really just flat number sequences structured as a 2D list: 基于这样的想法,即排列实际上只是结构为2D列表的平数序列:

from itertools import permutations

def tbl_perms(table):
    flat = (j for i in table for j in i)
    flat_permutations = iter(sorted(set(permutations(flat))))

    # convert back to the original structure
    while flat_permutations:
        flat_table = list(flat_permutations.next())  # because you can't pop() from tuple
        yield [[flat_table.pop(0) for _ in row] for row in table]

result = tbl_perms([[1, 1], [0, 0]])
pprint(list(result))

result = tbl_perms([[1, 1, 1], [0, 0, 0]])
pprint(list(result))

result = tbl_perms([[1, 2, 3], ['a', 'b']])
pprint(list(result))

Output: 输出:

[[[0, 0], [1, 1]], [[0, 1], [0, 1]], [[0, 1], [1, 0]], [[1, 0], [0, 1]], [[1, 0], [1, 0]], [[1, 1], [0, 0]]]
[[[0, 0, 0], [1, 1, 1]], [[0, 0, 1], [0, 1, 1]], [[0, 0, 1], [1, 0, 1]], [[0, 0, 1], [1, 1, 0]], [[0, 1, 0], [0, 1, 1]], [[0, 1, 0], [1, 0, 1]], [[0, 1, 0], [1, 1, 0]], [[0, 1, 1], [0, 0, 1]], [[0, 1, 1], [0, 1, 0]], [[0, 1, 1], [1, 0, 0]], [[1, 0, 0], [0, 1, 1]], [[1, 0, 0], [1, 0, 1]], [[1, 0, 0], [1, 1, 0]], [[1, 0, 1], [0, 0, 1]], [[1, 0, 1], [0, 1, 0]], [[1, 0, 1], [1, 0, 0]], [[1, 1, 0], [0, 0, 1]], [[1, 1, 0], [0, 1, 0]], [[1, 1, 0], [1, 0, 0]], [[1, 1, 1], [0, 0, 0]]]
[[[1, 2, 3], ['a', 'b']], [[1, 2, 3], ['b', 'a']], [[1, 2, 'a'], [3, 'b']], [[1, 2, 'a'], ['b', 3]], [[1, 2, 'b'], [3, 'a']], [[1, 2, 'b'], ['a', 3]], [[1, 3, 2], ['a', 'b']], [[1, 3, 2], ['b', 'a']], [[1, 3, 'a'], [2, 'b']], [[1, 3, 'a'], ['b', 2]], [[1, 3, 'b'], [2, 'a']], [[1, 3, 'b'], ['a', 2]], [[1, 'a', 2], [3, 'b']], [[1, 'a', 2], ['b', 3]], [[1, 'a', 3], [2, 'b']], [[1, 'a', 3], ['b', 2]], [[1, 'a', 'b'], [2, 3]], [[1, 'a', 'b'], [3, 2]], [[1, 'b', 2], [3, 'a']], [[1, 'b', 2], ['a', 3]], [[1, 'b', 3], [2, 'a']], [[1, 'b', 3], ['a', 2]], [[1, 'b', 'a'], [2, 3]], [[1, 'b', 'a'], [3, 2]], [[2, 1, 3], ['a', 'b']], [[2, 1, 3], ['b', 'a']], [[2, 1, 'a'], [3, 'b']], [[2, 1, 'a'], ['b', 3]], [[2, 1, 'b'], [3, 'a']], [[2, 1, 'b'], ['a', 3]], [[2, 3, 1], ['a', 'b']], [[2, 3, 1], ['b', 'a']], [[2, 3, 'a'], [1, 'b']], [[2, 3, 'a'], ['b', 1]], [[2, 3, 'b'], [1, 'a']], [[2, 3, 'b'], ['a', 1]], [[2, 'a', 1], [3, 'b']], [[2, 'a', 1], ['b', 3]], [[2, 'a', 3], [1, 'b']], [[2, 'a', 3], ['b', 1]], [[2, 'a', 'b'], [1, 3]], [[2, 'a', 'b'], [3, 1]], [[2, 'b', 1], [3, 'a']], [[2, 'b', 1], ['a', 3]], [[2, 'b', 3], [1, 'a']], [[2, 'b', 3], ['a', 1]], [[2, 'b', 'a'], [1, 3]], [[2, 'b', 'a'], [3, 1]], [[3, 1, 2], ['a', 'b']], [[3, 1, 2], ['b', 'a']], [[3, 1, 'a'], [2, 'b']], [[3, 1, 'a'], ['b', 2]], [[3, 1, 'b'], [2, 'a']], [[3, 1, 'b'], ['a', 2]], [[3, 2, 1], ['a', 'b']], [[3, 2, 1], ['b', 'a']], [[3, 2, 'a'], [1, 'b']], [[3, 2, 'a'], ['b', 1]], [[3, 2, 'b'], [1, 'a']], [[3, 2, 'b'], ['a', 1]], [[3, 'a', 1], [2, 'b']], [[3, 'a', 1], ['b', 2]], [[3, 'a', 2], [1, 'b']], [[3, 'a', 2], ['b', 1]], [[3, 'a', 'b'], [1, 2]], [[3, 'a', 'b'], [2, 1]], [[3, 'b', 1], [2, 'a']], [[3, 'b', 1], ['a', 2]], [[3, 'b', 2], [1, 'a']], [[3, 'b', 2], ['a', 1]], [[3, 'b', 'a'], [1, 2]], [[3, 'b', 'a'], [2, 1]], [['a', 1, 2], [3, 'b']], [['a', 1, 2], ['b', 3]], [['a', 1, 3], [2, 'b']], [['a', 1, 3], ['b', 2]], [['a', 1, 'b'], [2, 3]], [['a', 1, 'b'], [3, 2]], [['a', 2, 1], [3, 'b']], [['a', 2, 1], ['b', 3]], [['a', 2, 3], [1, 'b']], [['a', 2, 3], ['b', 1]], [['a', 2, 'b'], [1, 3]], [['a', 2, 'b'], [3, 1]], [['a', 3, 1], [2, 'b']], [['a', 3, 1], ['b', 2]], [['a', 3, 2], [1, 'b']], [['a', 3, 2], ['b', 1]], [['a', 3, 'b'], [1, 2]], [['a', 3, 'b'], [2, 1]], [['a', 'b', 1], [2, 3]], [['a', 'b', 1], [3, 2]], [['a', 'b', 2], [1, 3]], [['a', 'b', 2], [3, 1]], [['a', 'b', 3], [1, 2]], [['a', 'b', 3], [2, 1]], [['b', 1, 2], [3, 'a']], [['b', 1, 2], ['a', 3]], [['b', 1, 3], [2, 'a']], [['b', 1, 3], ['a', 2]], [['b', 1, 'a'], [2, 3]], [['b', 1, 'a'], [3, 2]], [['b', 2, 1], [3, 'a']], [['b', 2, 1], ['a', 3]], [['b', 2, 3], [1, 'a']], [['b', 2, 3], ['a', 1]], [['b', 2, 'a'], [1, 3]], [['b', 2, 'a'], [3, 1]], [['b', 3, 1], [2, 'a']], [['b', 3, 1], ['a', 2]], [['b', 3, 2], [1, 'a']], [['b', 3, 2], ['a', 1]], [['b', 3, 'a'], [1, 2]], [['b', 3, 'a'], [2, 1]], [['b', 'a', 1], [2, 3]], [['b', 'a', 1], [3, 2]], [['b', 'a', 2], [1, 3]], [['b', 'a', 2], [3, 1]], [['b', 'a', 3], [1, 2]], [['b', 'a', 3], [2, 1]]]

At this point, this question has been up for 5 years, but I found a slightly better answer than the one given (which was quite helpful). 在这一点上,这个问题已经持续了5年,但我找到了比给定的更好的答案(这非常有帮助)。 This answer accounts for larger 2d arrays. 这个答案占了更大的2d阵列。

from itertools import permutations, chain
from pprint import pprint
d = np.array([[1, 1], [0, 0]])
pprint([np.array(i).reshape(d.shape).tolist() for i in set(permutations(chain.from_iterable(d)))])

OUTPUT: OUTPUT:

[[[1, 1], [0, 2], [2, 0]],
 [[1, 0], [1, 0], [2, 2]],
 [[1, 0], [0, 2], [1, 2]],
 [[1, 2], [1, 0], [2, 0]],
 [[1, 0], [1, 2], [0, 2]],
 [[2, 1], [0, 2], [1, 0]],
 [[2, 1], [0, 0], [2, 1]],
 [[1, 2], [0, 2], [1, 0]],
 [[2, 0], [0, 2], [1, 1]],
 [[2, 1], [0, 1], [0, 2]],
 [[1, 1], [2, 0], [0, 2]],
 [[2, 0], [1, 0], [1, 2]],
 [[1, 0], [2, 2], [0, 1]],
 [[1, 2], [0, 1], [0, 2]],
 [[0, 2], [2, 0], [1, 1]],
 ...

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

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