Вычитание 2 списков в Python
Прямо сейчас у меня есть значения vector3, представленные в виде списков. Есть ли способ вычесть 2 из этих значений, таких как вектор3, как
[2,2,2] - [1,1,1] = [1,1,1]
Должен ли я использовать кортежи?
Если ни один из них не определяет эти операнды для этих типов, я могу определить это вместо этого?
Если нет, я должен создать новый класс vector3?
18 ответов
Если это то, что вы делаете часто и с разными операциями, вам, вероятно, следует создать класс для обработки подобных случаев или лучше использовать какую-нибудь библиотеку, например Numpy.
В противном случае ищите списки, используемые встроенной функцией zip:
[a_i - b_i for a_i, b_i in zip(a, b)]
Вот альтернатива списку пониманий. Карта перебирает список (ы) (последние аргументы), делая это одновременно, и передает их элементы в качестве аргументов функции (первый аргумент). Возвращает результирующий список.
map(operator.sub, a, b)
Этот код потому, что имеет меньший синтаксис (что для меня более эстетично), и, очевидно, он работает на 40% быстрее для списков длиной 5 (см. Комментарий Бобинса). Тем не менее, любое решение будет работать.
Если ваши списки a и b, вы можете сделать:
map(int.__sub__, a, b)
Но вы, вероятно, не должны. Никто не будет знать, что это значит.
Я бы тоже порекомендовал NumPy
Он не только быстрее выполняет векторную математику, но также имеет множество удобных функций.
Если вы хотите что-то еще быстрее для 1d векторов, попробуйте vop
Это похоже на MatLab, но бесплатно и прочее. Вот пример того, что вы будете делать
from numpy import matrix
a = matrix((2,2,2))
b = matrix((1,1,1))
ret = a - b
print ret
>> [[1 1 1]]
Boom.
Если у вас есть два списка с именами "a" и "b", вы можете сделать: [m - n for m,n in zip(a,b)]
Было предложено много решений.
Если вас интересует скорость, вот обзор различных решений относительно скорости (от самого быстрого до самого медленного).
import timeit
import operator
a = [2,2,2]
b = [1,1,1] # we want to obtain c = [2,2,2] - [1,1,1] = [1,1,1
%timeit map(operator.sub, a, b)
176 ns ± 7.18 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit map(int.__sub__, a, b)
179 ns ± 4.95 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit map(lambda x,y: x-y, a,b)
189 ns ± 8.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit [a_i - b_i for a_i, b_i in zip(a, b)]
421 ns ± 18.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit [x - b[i] for i, x in enumerate(a)]
452 ns ± 17.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each
%timeit [a[i] - b[i] for i in range(len(a))]
530 ns ± 16.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit list(map(lambda x, y: x - y, a, b))
546 ns ± 16.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit np.subtract(a,b)
2.68 µs ± 80.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit list(np.array(a) - np.array(b))
2.82 µs ± 113 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit np.matrix(a) - np.matrix(b)
12.3 µs ± 437 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
С использованием
map
явно самый быстрый. На удивление самый медленный. Получается, что стоимость первого преобразования списков
a
и
b
к
numpy
array - это узкое место, которое перевешивает любой выигрыш в эффективности от векторизации.
%timeit a = np.array([2,2,2]); b=np.array([1,1,1])
1.55 µs ± 54.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
a = np.array([2,2,2])
b = np.array([1,1,1])
%timeit a - b
417 ns ± 12.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Немного другой класс Vector.
class Vector( object ):
def __init__(self, *data):
self.data = data
def __repr__(self):
return repr(self.data)
def __add__(self, other):
return tuple( (a+b for a,b in zip(self.data, other.data) ) )
def __sub__(self, other):
return tuple( (a-b for a,b in zip(self.data, other.data) ) )
Vector(1, 2, 3) - Vector(1, 1, 1)
Если вы планируете выполнять несколько простых строк, было бы лучше реализовать свой собственный класс и переопределить соответствующие операторы при их применении в вашем случае.
Взято из математики в Python:
class Vector:
def __init__(self, data):
self.data = data
def __repr__(self):
return repr(self.data)
def __add__(self, other):
data = []
for j in range(len(self.data)):
data.append(self.data[j] + other.data[j])
return Vector(data)
x = Vector([1, 2, 3])
print x + x
Для того, кто писал код на Pycharm, он также оживляет и других.
import operator
Arr1=[1,2,3,45]
Arr2=[3,4,56,78]
print(list(map(operator.sub,Arr1,Arr2)))
Сочетание map
а также lambda
Функции в Python - хорошее решение для такой проблемы:
a = [2,2,2]
b = [1,1,1]
map(lambda x,y: x-y, a,b)
zip
функция - еще один хороший выбор, о чем свидетельствует @UncleZeiv
Этот ответ показывает, как писать "нормальный / простой для понимания" питонический код.
Я предлагаю не использовать zip
поскольку не все об этом знают.
В решениях используются списки и стандартные встроенные функции.
Альтернатива 1 (рекомендуется):
a = [2, 2, 2]
b = [1, 1, 1]
result = [a[i] - b[i] for i in range(len(a))]
Рекомендуется, так как он использует только самые основные функции Python
Альтернатива 2:
a = [2, 2, 2]
b = [1, 1, 1]
result = [x - b[i] for i, x in enumerate(a)]
Альтернатива 3 (как упомянуто BioCoder):
a = [2, 2, 2]
b = [1, 1, 1]
result = list(map(lambda x, y: x - y, a, b))
использовать цикл for
a = [3,5,6]
b = [3,7,2]
c = []
for i in range(len(a)):
c.append(a[i] - b[i])
print(c)
вывод [0, -2, 4]
arr1=[1,2,3]
arr2=[2,1,3]
ls=[arr2-arr1 for arr1,arr2 in zip(arr1,arr2)]
print(ls)
>>[1,-1,0]
Если вы хотите, чтобы результат в списке:
list(numpy.array(list1)-numpy.array(list2))
если не удалить список.
Очень просто
list1=[1,2,3,4,5]
list2=[1,2]
list3=[]
# print(list1-list2)
for element in list1:
if element not in list2:
list3.append(element)
print(list3)