#python
Вопрос:
Я не уверен, какой правильный термин здесь используется для умножения, но мне нужно умножить элемент из списка A, например, на каждый элемент в списке B и создать новый список для новых элементов, чтобы общая длина нового списка составляла len(A)*len(B).
В качестве примера
A = [1,3,5], B=[4,6,8]
Мне нужно умножить их вместе, чтобы получить
C = [4,6,8,12,18,24,20,30,40]
Я исследовал это и обнаружил, что в itertools(продукте) есть именно то, что мне нужно, однако это для определенного количества списков, и мне нужно обобщить любое количество списков по запросу пользователя.
У меня сейчас нет доступа к полному коду, но код запрашивает у пользователя некоторые списки (может быть любое количество списков), и списки могут содержать любое количество элементов в списках (но все списки содержат одинаковое количество элементов). Затем эти списки сохраняются в одном большом списке.
Например (ввод данных пользователем)
A = [2,5,8], B= [4,7,3]
Большой список будет
C = [[2,5,8],[4,7,3]]
В этом случае в большом списке есть два списка, но в целом это может быть любое количество списков.
Как только в коде появится это, у меня будет
print([a*b for a,b in itertools.product(C[0],C[1])])
>> [8,14,6,20,35,15,32,56,24]
Результат этого именно то, что я хочу, однако в данном случае код написан ровно для двух списков, и мне нужно, чтобы он был обобщен на n списков.
Я думал о создании цикла, чтобы каким-то образом повторить его n раз, но до сих пор мне это не удавалось. Поскольку C может иметь любую длину, то циклу нужен способ узнать, когда он достигнет конца списка. Мне это не нужно для вычисления продукта с n списками одновременно
print([a0*a1*...*a(n-1) for a0,a1,...,a(n-1) in itertools.product(C[0],C[1],C[2],...C[n-1])])
Цикл может умножать два списка одновременно, а затем использовать результат этого умножения против следующего списка в C и так далее до C[n-1].
Я был бы признателен за любой совет, чтобы убедиться, что я, по крайней мере, двигаюсь в правильном направлении.
p.s. Я использую numpy, и списки представляют собой массивы.
Ответ №1:
Вы можете передать переменное количество аргументов в itertools.product
with *
. *
является оператором распаковки, который распаковывает список и передает его значения значениям списка в функцию, как если бы они передавались отдельно.
import itertools
import math
A = [[1, 2], [3, 4], [5, 6]]
result = list(map(math.prod, itertools.product(*A)))
print(result)
Результат:
[15, 18, 20, 24, 30, 36, 40, 48]
Вы можете найти много объяснений в Интернете об *
операторе. Короче говоря, если вы вызовете функцию типа f(*lst)
, она будет примерно эквивалентна f(lst[0], lst[1], ..., lst[len(lst) - 1])
. Таким образом, это избавит вас от необходимости знать длину списка.
Редактировать: Я только что понял, что math.prod
это функция 3.8 . Если вы используете более старую версию Python, вы можете заменить ее эквивалентом numpy, np.prod
.
Ответ №2:
Вы можете использовать функцию сокращения, предназначенную именно для этих типов операций, которая основана на рекурсии и накоплении. Я привожу вам пример с примитивной функцией, чтобы вы могли лучше понять ее функциональность:
lists = [
[4, 6, 8],
[1, 3, 5]
]
def reduce(function, iterable, initializer=None):
it = iter(iterable)
if initializer is None:
value = next(it)
else:
value = initializer
for element in it:
value = function(value, element)
return value
def cmp(a, b):
for x in a:
for y in b:
yield x*y
summed = list(reduce(cmp, lists))
# OUTPUT
[4, 12, 20, 6, 18, 30, 8, 24, 40]
В случае, если вам нужно его отсортировать, просто воспользуйтесь функцией sort ().