在Python中生成循环移位/缩小的拉丁方
问题内容:
只是想知道在Python中生成列表的所有循环移位的最有效方法是什么。在任一方向上。例如,给定一个list [1, 2, 3, 4]
,我想生成其中一个:
[[1, 2, 3, 4],
[4, 1, 2, 3],
[3, 4, 1, 2],
[2, 3, 4, 1]]
通过将最后一个元素移到最前面来生成下一个排列,或者:
[[1, 2, 3, 4],
[2, 3, 4, 1],
[3, 4, 1, 2],
[4, 1, 2, 3]]
下一个排列是通过将第一个元素移到后面来生成的。
第二种情况对我来说稍微有点有趣,因为它导致减小的拉丁方(第一种情况也给出了一个拉丁方,只是没有减小),这就是我正在尝试进行实验性块设计的方法。实际上,它们与第一种情况并没有什么不同,因为它们只是彼此重新排序,但是顺序仍然很重要。
我对第一种情况的当前实现是:
def gen_latin_square(mylist):
tmplist = mylist[:]
latin_square = []
for i in range(len(mylist)):
latin_square.append(tmplist[:])
tmplist = [tmplist.pop()] + tmplist
return latin_square
对于第二种情况:
def gen_latin_square(mylist):
tmplist = mylist[:]
latin_square = []
for i in range(len(mylist)):
latin_square.append(tmplist[:])
tmplist = tmplist[1:] + [tmplist[0]]
return latin_square
第一种情况似乎对我来说应该是相当有效的,因为它使用pop()
,但是在第二种情况下您不能这样做,所以我想听听有关如何更有效地执行此操作的想法。也许有些东西itertools
会有所帮助?也许第二种情况是双头队列?
问题答案:
对于第一部分,最简洁的方法可能是
a = [1, 2, 3, 4]
n = len(a)
[[a[i - j] for i in range(n)] for j in range(n)]
# [[1, 2, 3, 4], [4, 1, 2, 3], [3, 4, 1, 2], [2, 3, 4, 1]]
第二部分
[[a[i - j] for i in range(n)] for j in range(n, 0, -1)]
# [[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]
尽管我没有做任何计时,但它们也应该比您的代码更有效。