Мне нужен функционал 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 операторов, каждый из которых при применении к списку дает один из переставленных списков.
Пожалуйста, обновите свой вопрос с примером использования, который предполагает, что у вас уже есть функция, которая создает функции.
Также вы можете просто сохранить параметры в словаре. Но, пожалуйста, предоставьте желаемый результат.
Кстати, вам, вероятно, лучше использовать itertools.permutations, чем изобретать велосипед.
Он у вас уже есть lambda a, j: [a[i - j] for i in range(len(a))]. Это функция, которая по заданному списку и смещению возвращает повернутый список.
@DeepSpace Вращения не являются перестановками. Они представляют собой подмножество, поддерживающее циклическую смежность.
@ДанД. достаточно справедливо, но я уверен, что есть рецепт itertools, который не заставит нас (или ОП) изобретать велосипед :) (не то, чтобы в данном случае это было так сложно...)
обычное определение "циклической перестановки" - это совершенно другое понятие, чем то, о чем вы просите.






Вы можете написать функцию, которая возвращает функции:
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() в каждом экземпляре.
Может быть, немного поздно, но это так невероятно блестяще! Просто нужно было сказать это; действительно впечатляет! Спасибо; это было как раз то, что мне было нужно.
Я не совсем уверен, какова цель этого упражнения, но вы можете сделать это с частичными функциями.
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 Думаю, мне нужно больше узнать о них!
Вы можете сделать следующее. Вызов функции cyclic_perm в input_list вернет список операторов (функций), которые при вызове в input_list дадут вам желаемый результат.
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))
Я интерпретирую ваш запрос как «учитывая количество циклов 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 сдвигов и
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 делится на __getitem__() из mit.circular_shifts()fсочиняет последняя частичная функцияУстановите эту стороннюю библиотеку через > pip install more_itertools.
Я не уверен, что означает последнее предложение. Не могли бы вы привести пример?