2015-11-23 3 views
0

Представьте, что у вас есть два списка.Python: всякая возможная дискретная функция в двух списках

list1 = ['a', 'b', 'c'] 
list2 = ['x', 'y'] 

, что это функция, которая дает Вам все возможные функции из области list1 в кообласть list2? Ответ в этом случае будет

[ [('a', 'x'), ('b', 'y')], 
    [('a', 'x'), ('c', 'y')], 
    [('b', 'x'), ('a', 'y')], 
    [('b', 'x'), ('c', 'y')], 
    [('c', 'x'), ('a', 'y')], 
    [('c', 'x'), ('b', 'y')] ] 

Это более общий случай this question and answer, который является ответом на этот вопрос, когда песни1 и песни2 имеют одинаковый размер.

Предположим, вы не знаете, что больше, и любой из них может быть 0, 1 или многими элементами. Предпочтительно это должно быть выражено как некоторая комбинация функций itertools.

--EDITS--

Лучшее, что я до сих пор является:

def everyPossibleAssignment(A, B): 

if len(A) < len(B): return [list(zip(A, P)) for P in permutations(B, len(A))] 
else: print "A must be smaller in size than B" 

, но я уверен, что лучше.

+4

Если 'list1' - это домен, то ваши функции не должны характеризоваться тремя парами (a ->?, b ->?, c ->?), а не два? – senshin

+2

Откуда у? –

+1

['продукт' от itertools] (https://docs.python.org/2/library/itertools.html#itertools.product) –

ответ

1

(ОП уточнил в комментариях, что он фактически не хочет функций, а скорее частичных биекций между этими двумя наборами. Поэтому этот ответ не делает то, что хочет OP. Я оставляю его здесь в любом случае, если он представляет интерес . для будущих читателей)


Вы, вероятно, хотите взять product домена с |domain| копиями значений:

from itertools import product 

list1 = ['a', 'b', 'c'] 
list2 = ['x', 'y'] 

# The `zip` is just bookkeeping to transform (('a', 'b', 'c'), ('x', 'y', 'y')) 
# into (('a', 'x'), ('b', 'y'), ('c', 'y')) 
functions = [ 
    zip(*x) for x 
    in product([list1], product(list2, repeat=len(list1))) 
    ] 

for function in functions: 
    print(list(function)) 

Выход:

[('a', 'x'), ('b', 'x'), ('c', 'x')] 
[('a', 'x'), ('b', 'x'), ('c', 'y')] 
[('a', 'x'), ('b', 'y'), ('c', 'x')] 
[('a', 'x'), ('b', 'y'), ('c', 'y')] 
[('a', 'y'), ('b', 'x'), ('c', 'x')] 
[('a', 'y'), ('b', 'x'), ('c', 'y')] 
[('a', 'y'), ('b', 'y'), ('c', 'x')] 
[('a', 'y'), ('b', 'y'), ('c', 'y')] 

Это правильно производит 0 функций, когда кодомен пуст, но домен не является, и 1 функция (пустая функция), когда домен пуст. (Я предполагаю, что вам нужны только общие функции. Если вы хотите получить частичные функции, то возьмите продукты по combinations домена длины 0, 1, ..., |domain| вместо домена только домена.)

1

Ответ из другого вопроса работает очень хорошо, если вы перемещаете некоторые вещи:

In [15]: list(list(zip(p, r)) for (r, p) in zip(repeat(list2), permutations(list1))) 
Out[15]: 
[[('a', 'x'), ('b', 'y')], 
[('a', 'x'), ('c', 'y')], 
[('b', 'x'), ('a', 'y')], 
[('b', 'x'), ('c', 'y')], 
[('c', 'x'), ('a', 'y')], 
[('c', 'x'), ('b', 'y')]] 
+0

Если это то, что вы хотите, OP, все в порядке, но вы должны знать, что это не «всевозможная [общая] функция из домена списка1 в кодомену списка2». Там должны быть '| list2 |^| list1 |' такие функции, которые в этом случае равны 8, а не 6. – senshin

+0

Я думаю, что я не совсем правильно ответил на мой вопрос. Я не очень хочу функцию, не так ли? Потому что я не хочу, чтобы любые две части домена отображались на один и тот же член кодомена. В принципе, я хочу, если вы возьмете оба списка, каждая карта «один-к-одному» между этими двумя списками. –

+0

@AlexLenail В этом случае то, что вы действительно хотите, это «частичные биекции» между этими двумя списками. Должно существовать 'min (| domain |, | codomain |)!' Многие из них.Я думаю, что этот ответ работает правильно для генерации частичных биекций, но для домена или codomain из 4 элементов и более он создает повторяющиеся записи, которые вам нужно отфильтровать. – senshin

Смежные вопросы