#python #list #python-2.7
#python #Список #python-2.7
Вопрос:
Я не могу использовать Numpy или любую другую библиотечную функцию, поскольку это вопрос, который я должен решить, я должен определить свой собственный путь.
Я пишу функцию, которая принимает два списка (двумерных) в качестве аргументов. Функция должна вычислить поэлементное произведение обоих списков и сохранить их в третьем списке и вернуть этот результирующий список из функции. Примером входных списков являются:
список 1:
[[2,3,5,6,7],[5,2,9,3,7]]
список 2:
[[5,2,9,3,7],[1,3,5,2,2]]
Функция выводит следующий список:
[[10, 6, 45, 18, 49], [5, 6, 45, 6, 14]]
То есть 2*5=10
, 3*2=6
5*9=45
… и так далее.
Ниже приведен мой код, но он предназначен только для списка с двумя списками (элементами) внутри, как в примере выше, и отлично работает для этого, но я хочу отредактировать свой код так, чтобы независимо от того, сколько списков (элементов) имеется в двумерном списке, он должен выводить свой поэлементный продукт в новом двумерном списке, например, он также должен работать для
[[5,2,9,3,7],[1,3,5,2,2],[1,3,5,2,2]]
или
[[5,2,9,3,7],[1,3,5,2,2],[1,3,5,2,2],[5,2,9,3,7]]
или любое количество списков, которые есть во всем списке.
def ElementwiseProduct(l,l2):
i=0
newlist=[] #create empty list to put prouct of elements in later
newlist2=[]
newlist3=[] #empty list to put both new lists which will have proudcts in them
while i==0:
a=0
while a<len(l[i]):
prod=l[i][a]*l2[i][a] #corresponding product of lists elements
newlist.append(prod) #adding the products to new list
a =1
i =1
while i==1:
a=0
while a<len(l[i]):
prod=l[i][a]*l2[i][a] #corresponding product of lists elements
newlist2.append(prod) #adding the products to new list
a =1
i =1
newlist3.append(newlist)
newlist3.append(newlist2)
print newlist3
#2 dimensional list example
list1=[[2,3,5,6,7],[5,2,9,3,7]]
list2=[[5,2,9,3,7],[1,3,5,2,2]]
ElementwiseProduct(list1,list2)
Комментарии:
1. Вы должны использовать zip в компиляторе списков
2. Ответ Мозеса Коледоя должен сделать свое дело без Numpy
Ответ №1:
Вы можете zip
использовать два списка для понимания списка, затем дополнить zip
полученные подсписки и, наконец, умножить элементы:
list2 = [[5,2,9,3,7],[1,3,5,2,2]]
list1 = [[2,3,5,6,7],[5,2,9,3,7]]
result = [[a*b for a, b in zip(i, j)] for i, j in zip(list1, list2)]
print(result)
# [[10, 6, 45, 18, 49], [5, 6, 45, 6, 14]]
Если в списках / подсписках разное количество элементов, itertools.izip_longest
может использоваться для генерации значений заполнения, таких как пустой подсписк для меньшего списка или 0 для более короткого подсписка:
from itertools import izip_longest
list1 = [[2,3,5,6]]
list2 = [[5,2,9,3,7],[1,3,5,2,2]]
result = [[a*b for a, b in izip_longest(i, j, fillvalue=0)]
for i, j in izip_longest(list1, list2, fillvalue=[])]
print(result)
# [[10, 6, 45, 18, 0], [0, 0, 0, 0, 0]]
Вы можете изменить внутреннее значение fillvalue
с 0 на 1, чтобы возвращать элементы в более длинных подсписках как есть, вместо однородного 0.
Ссылка:
Комментарии:
1. Вы также могли бы ввести расширение параметров с
result = [[a*b for a, b in zip(*e)] for e in zip(list1, list2)]
2. @MadPhysicist Это выглядит аккуратнее, но потребует некоторых объяснений о том, как работает распаковка 🙂
3. Добавьте использование
reduce
иoperator.mul
, и этот ответ станет золотым
Ответ №2:
Вот функция, которая может обрабатывать любой тип итерации, вложенный на любой уровень (любое количество измерений, а не только 2):
def elementwiseProd(iterA, iterB):
def multiply(a, b):
try:
iter(a)
except TypeError:
# You have a number
return a * b
return elementwiseProd(a, b)
return [multiply(*pair) for pair in zip(iterA, iterB)]
Эта функция работает рекурсивно. Для каждого элемента в списке проверяется, является ли элемент итеративным. Если это так, то выходной элемент представляет собой список, содержащий поэлементное умножение повторяющихся элементов. В противном случае возвращается произведение чисел.
Это решение будет работать со смешанными вложенными типами. Здесь делается пара предположений о том, что все уровни вложенности имеют одинаковый размер, и что элемент, являющийся числом в одной итерации (по сравнению с вложенной итерацией), всегда является числом в другой.
Фактически, этот фрагмент может быть расширен для применения любой n-арной функции к любым n итерабельным:
def elementwiseApply(op, *iters):
def apply(op, *items):
try:
iter(items[0])
except TypeError:
return op(*items)
return elementwiseApply(op, *items)
return [apply(op, *items) for items in zip(*iters)]
Чтобы выполнить умножение, вы должны использовать operator.mul
:
from operator import mul
list1=[[2,3,5,6,7], [5,2,9,3,7]]
list2=[[5,2,9,3,7], [1,3,5,2,2]]
elementwiseApply(mul, list1, list2)
производит
[[10, 6, 45, 18, 49], [5, 6, 45, 6, 14]]
Комментарии:
1. Мило, но я подозреваю, что это может быть слишком сложным для OP. OTOH, это может представлять интерес для других читателей.
2. @PM2Ring. Я написал это еще тогда, когда подумал, что, похоже, требуется обрабатывать массивы любой размерности. Сохранил его именно по той причине, которую вы указываете. Не ожидайте, что это будет общепринятый ответ, но это полезный пример.
Ответ №3:
В Python, как правило, лучше выполнять цикл непосредственно над элементами в списке, а не выполнять цикл косвенно, используя индексы. Это упрощает чтение кода, а также повышает его эффективность, поскольку позволяет избежать утомительной индексной арифметики.
Вот как решить вашу проблему, используя традиционные for
циклы. Мы используем встроенную zip
функцию для выполнения итерации по двум (или более) спискам одновременно.
def elementwise_product(list1,list2):
result = []
for seq1, seq2 in zip(list1,list2):
prods = []
for u, v in zip(seq1, seq2):
prods.append(u * v)
result.append(prods)
return result
list1=[[2,3,5,6,7], [5,2,9,3,7]]
list2=[[5,2,9,3,7], [1,3,5,2,2]]
print(elementwise_product(list1,list2))
вывод
[[10, 6, 45, 18, 49], [5, 6, 45, 6, 14]]
Мы можем использовать понимание списков, чтобы сделать этот код намного более компактным. Поначалу это может показаться сложным для чтения, но с практикой вы привыкнете к пониманию списка.
def elementwise_product(list1,list2):
return [[u*v for u, v in zip(seq1, seq2)]
for seq1, seq2 in zip(list1,list2)]
Комментарии:
1. Мне нравится этот ответ, потому что он затрагивает самые основные проблемы с операционным кодом. Это, вероятно, наиболее полезно для тех, кто только начинает изучать Python.
Ответ №4:
Вы могли бы использовать массивы numpy. Это ваш лучший вариант, поскольку они выполняются в фоновом режиме C и, следовательно, намного быстрее в вычислительном отношении
Сначала установите numpy. Запустите свой терминал (CMD, если вы в Windows), введите
pip install numpy
или, если в Linux, sudo pip install numpy
Затем переходите к написанию своего кода
import numpy as np
list1=np.array([[2,3,5,6,7],[5,2,9,3,7]]) #2 dimensional list example
list2=np.array([[5,2,9,3,7],[1,3,5,2,2]])
prod = np.multiply(list1,list2)
# or simply, as suggested by Mad Physicist,
prod = list1*list2
Комментарии:
1. Надеюсь, вы не возражаете против редактирования импорта. OP кажется очень новым для Python, поэтому, вероятно, лучше всего быть явным.
2. Кроме того, вы могли бы просто сделать
list1 * list2
.3. Вам также пришлось бы установить numpy. OP также поручено написать свою собственную функцию, поэтому numpy не является вариантом в соответствии с первой строкой их вопроса. Я не могу использовать numpy ….
4. Спасибо, что указали на это @PadraicCunningham. Добавлено руководство по установке. Numpy — важная библиотека, поэтому я думаю, что он должен попробовать ее.
5. И @MadPhysicist Спасибо за предупреждение 🙂