在Python中生成循环移位/简化拉丁方
只是想知道在 Python 中生成列表的所有循环移位的最有效方法是什么。在任一方向。例如,给定一个列表 [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
中有一些东西可以提供帮助?或者也许是第二种情况的双端队列?
Was just wondering what's the most efficient way of generating all the circular shifts of a list in Python. In either direction. For example, given a list [1, 2, 3, 4]
, I want to generate either:
[[1, 2, 3, 4],
[4, 1, 2, 3],
[3, 4, 1, 2],
[2, 3, 4, 1]]
where the next permutation is generated by moving the last element to the front, or:
[[1, 2, 3, 4],
[2, 3, 4, 1],
[3, 4, 1, 2],
[4, 1, 2, 3]]
where the next permutation is generated by moving the first element to the back.
The second case is slightly more interesting to me because it results in a reduced Latin square (the first case also gives a Latin square, just not reduced), which is what I'm trying to use to do experimental block design. It actually isn't that different from the first case since they're just re-orderings of each other, but order does still matter.
The current implementation I have for the first case is:
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
For the second case its:
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
The first case seems like it should be reasonably efficient to me, since it uses pop()
, but you can't do that in the second case, so I'd like to hear ideas about how to do this more efficiently. Maybe there's something in itertools
that will help? Or maybe a double-ended queue for the second case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您可以使用collections.deque:
它打印:
要将其更改为左旋转,只需将
g.rotate(1)
替换为g.rotate(-1)
。You can use collections.deque:
It prints:
To change it for left rotation just replace
g.rotate(1)
withg.rotate(-1)
.对于第一部分,最简洁的方法可能是
,对于第二部分,
这些也应该比您的代码更有效,尽管我没有做任何计时。
For the first part, the most concise way probably is
and for the second part
These should also be much more efficient than your code, though I did not do any timings.
切片“守恒定律”的变体
a = a[:i] + a[i:]
variation on slicing "conservation law"
a = a[:i] + a[i:]
more_itertools
是一个第三方库,提供了一个工具< a href="https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.circular_shifts" rel="nofollow noreferrer">循环排列:另请参阅 维基百科:
more_itertools
is a third-party library that offers a tool for cyclic permutations:See also Wikipedia:
@Bruno Lenzi 的答案似乎不起作用:
我在下面给出了正确的版本,但是 @f5r5e5d 的解决方案更快。
出于计时目的,我删除了
use_cycle
和use_slice
中的打印语句。The answer by @Bruno Lenzi does not seem to work:
I give a correct version below, however the solution by @f5r5e5d is faster.
I removed the print statement in
use_cycle
anduse_slice
for timing purposes.使用 itertools 避免索引:
Using itertools to avoid indexing:
这将是我的解决方案。
这将输出以下内容:
您还可以使用
pop
而不是使用列表切片,但pop
的问题是它会返回一些内容。另外,上面的代码适用于任何长度的列表。我还没有检查代码的性能。我假设它会工作得更好。
您应该查看 Python 文档 以更好地理解列表切片。
This will be my solution.
This will output the following:
You can also use
pop
instead of using list slicing but the problem withpop
is that it will return something.Also the above code will work for any length of list. I have not checked for performance of the code. I am assuming that it will work better.
You should have a look at Python docs for getting a good understanding of List slicing.