Python中的循环置换操作符

6

我需要一个Python函数(创建函数的函数),它可以为长度为N的列表创建所有循环置换操作符。

对于Python列表a(例如a = [1, 2, 3, 4,5,6],N = 6),可以定义一个函数:

def cyclic_perm(a):
    n = len(a)
    b = [[a[i - j] for i in range(n)] for j in range(n)]
    return b

这个函数可以给出一个列表的所有可能循环排列,本例中有6个列表。

我希望该函数不返回列表本身,而是返回(在本例中)6个操作符,当应用于该列表时,每个操作符都会返回其中一种排列后的列表。


我不确定最后一句话的意思。你能提供一个例子吗? - DeepSpace
请更新您的问题,提供一个使用示例,假设您已经拥有创建函数的功能。 - quamrana
1
顺便说一句,你最好使用 itertools.permutations 而不是重新发明轮子。 - DeepSpace
1
@DeepSpace 旋转不是排列。它们是一个子集,保持循环相邻。 - Dan D.
“循环置换”的通常定义与您所询问的概念完全不同。” - user2357112
显示剩余3条评论
5个回答

5

我不太确定这个练习的目标是什么,但您可以使用部分函数完成此操作。

from functools import partial

def reorder_from_idx(idx, a):
    return a[idx:] + a[:idx]

def cyclic_perm(a):
    return [partial(reorder_from_idx, i) for i in range(len(a))]


a = [1, 2, 3, 4, 5, 6]
result = cyclic_perm(a)
print(result)
#[functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 0),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 1),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 2),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 3),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 4),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 5)]
result[3](a)
#[4, 5, 6, 1, 2, 3]

很好的偏函数示例 @ParitoshSingh +1 猜我需要更多地了解它们! - Devesh Kumar Singh

4
你可以编写一个返回函数的函数:
def cyclic_perm(a):
    n = len(a)
    b = [[a[i - j] for i in range(n)] for j in range(n)]
    return b

def cyclic_perm_func(a):
    n = len(a)
    def wrapper(a, n, j):
        def cyc():
            return [a[i - j] for i in range(n)]
        return cyc
    b = [wrapper(a, n, j) for j in range(n)]
    return b

a = [1, 2, 3, 4,5,6]
print(cyclic_perm(a))  # Your original function
f = cyclic_perm_func(a) # f is now a list of functions
print([g() for g in f])  # Let's call each in turn

输出:

[[1, 2, 3, 4, 5, 6], [6, 1, 2, 3, 4, 5], [5, 6, 1, 2, 3, 4], [4, 5, 6, 1, 2, 3], [3, 4, 5, 6, 1, 2], [2, 3, 4, 5, 6, 1]]
[[1, 2, 3, 4, 5, 6], [6, 1, 2, 3, 4, 5], [5, 6, 1, 2, 3, 4], [4, 5, 6, 1, 2, 3], [3, 4, 5, 6, 1, 2], [2, 3, 4, 5, 6, 1]]

请注意,wrapper()是捕获每个实例中包装函数cyc()所需参数的方法。

也许有点晚了,但这太棒了!必须得说一下;真的很令人印象深刻!谢谢;这正是我所需要的。 - William Martens

1
也许这个方法有点慢,但为什么不直接使用模块化(mod)呢?例如:
def cycle(colors,n):
   return [colors[(n + i) % len(colors)] for i in range(len(colors))]

然后你可以使用以下代码获取排列列表:

[cycle(colors,j) for j in range(len(colors))]

1
您可以执行以下操作。在输入列表上调用函数将返回运算符(函数)列表,当在输入列表上调用这些运算符时,将得到所需的结果。
input_list = [1, 2, 3, 4, 5, 6]


def cyclic_perm(a):
    n = len(a)
    result = []
    for j in range(n):
        def f(l, k=j):
            return list(map(lambda i: l[i - k], range(n)))
        result.append(f)
    return result


for op in cyclic_perm(input_list):
    print(op(input_list))


1
我理解你的请求是“给定一个循环次数n,实现一个函数,接受n并返回一个函数,当传入可迭代对象时,返回移位n个位置后的可迭代对象”。请参考more_itertools.circular_shifts输入:
import functools as ft

import more_itertools as mit


iterable = range(6, 10)

代码

def composed_shifts(n):
    """Return a function of `n` circular shifts."""
    def f(x):    
        return ft.partial(mit.circular_shifts(x).__getitem__, n)()
    return f

演示

composed_shifts(1)                                         # 1
# <function __main__.composed_shifts.<locals>.f(x)>

composed_shifts(1)(iterable)                               # 2
# (7, 8, 9, 6)

composed_shifts(3)(iterable)
# (9, 6, 7, 8)

详情

我们的composed_shifts()函数接受一个整数n,并且

  1. 返回一个函数
  2. 当传入一个可迭代对象时,返回mit.circular_shifts()中列表索引处的值。请参阅下面的详细信息。

循环移位是一种特定类型的循环置换,如下所示:

mit.circular_shifts(iterable))

输出

[(6, 7, 8, 9),                                             # 0 shifts
 (7, 8, 9, 6),                                             # 1   " 
 (8, 9, 6, 7),                                             # 2   " 
 (9, 6, 7, 8)]                                             # 3   "

如图所示,返回了所有循环移位的列表。我们只需要一个索引来选择特定的移位n。这个选择是通过__getitem__实现的,它被部分化以延迟对未来列表的索引。
总结:
  • 移位(索引)n被部分化到mit.circular_shifts()__getitem__()中。
  • 内部函数f组合后面的部分函数。
通过> pip install more_itertools安装这个第三方库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接