Odejmowanie 2 list w Pythonie

84

W tej chwili mam wartości vector3 reprezentowane jako listy. czy istnieje sposób na odjęcie 2 z tych wartości, takich jak vector3, na przykład

[2,2,2] - [1,1,1] = [1,1,1]

Czy powinienem używać krotek?

Jeśli żaden z nich nie definiuje tych operandów na tych typach, czy mogę je zamiast tego zdefiniować?

Jeśli nie, czy powinienem utworzyć nową klasę vector3?

Joan Venge
źródło

Odpowiedzi:

134

Jeśli jest to coś, co często robisz, i przy różnych operacjach, prawdopodobnie powinieneś utworzyć klasę do obsługi takich przypadków lub lepiej użyć jakiejś biblioteki, takiej jak Numpy .

W przeciwnym razie, poszukaj listowych używany z zamkiem wbudowanej funkcji:

[a_i - b_i for a_i, b_i in zip(a, b)]
UncleZeiv
źródło
83

Oto alternatywa dla list składanych. Map iteruje listę (y) (ostatnie argumenty), robiąc to jednocześnie, i przekazuje ich elementy jako argumenty do funkcji (pierwszy argument). Zwraca wynikową listę.

map(operator.sub, a, b)

Ten kod, ponieważ ma mniejszą składnię (co jest dla mnie bardziej estetyczne) i najwyraźniej jest o 40% szybszy dla list o długości 5 (patrz komentarz bobince'a). Mimo to oba rozwiązania będą działać.

Nikhil Chelliah
źródło
Zwykle widzę, że listy składane są ponownie polecane przez map (), chociaż może to być spowodowane tylko tym, że jest to bardziej przejrzysty kod ... nie jestem pewien, czy różnica w wydajności istnieje.
David Z
2
Mapa () wychodzi prawie 40% szybciej na Py2.6 przy odejmowaniu pięciu elementów. Zrozumienia są nowsze i bardziej przejrzyste tam, gdzie unikają lambda, ale do mapowania istniejących funkcji mapa może być nadal ładna ... szczególnie tutaj, gdzie można wykorzystać wbudowany zip.
bobince
1
działa to również dla array.array (chociaż wynikiem jest lista)
gens
5
wymagana jest klauzula „operator importu”; int .__ sub__ radzi sobie lepiej))
garej
13

Jeśli Twoje listy to a i b, możesz:

map(int.__sub__, a, b)

Ale prawdopodobnie nie powinieneś. Nikt nie będzie wiedział, co to znaczy.

rekurencyjny
źródło
1
Sam wpadłem na to z pływakami. W takim przypadku map(float.__sub__, a, b)działa. Dzięki za wskazówkę!
S3DEV
9

Musiałbym polecam NumPy także

Jest nie tylko szybszy do wykonywania obliczeń wektorowych, ale ma również mnóstwo wygodnych funkcji.

Jeśli chcesz czegoś jeszcze szybszego dla wektorów 1d, wypróbuj vop

Jest podobny do MatLab, ale darmowy i takie tam. Oto przykład tego, co byś zrobił

from numpy import matrix
a = matrix((2,2,2))
b = matrix((1,1,1))
ret = a - b
print ret
>> [[1 1 1]]

Bum.

mikelikespie
źródło
1
np.arraybyłoby prostszym rozwiązaniem
garej
6

Jeśli masz dwie listy o nazwach „a” i „b”, możesz: [m - n for m,n in zip(a,b)]

Andy Mikula
źródło
5
import numpy as np
a = [2,2,2]
b = [1,1,1]
np.subtract(a,b)
user3503711
źródło
4

Nieco inna klasa 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)
S.Lott
źródło
3

Jeśli planujesz wykonywać więcej niż zwykłe wkładki typu one, byłoby lepiej zaimplementować własną klasę i zastąpić odpowiednie operatory, które mają zastosowanie w twoim przypadku.

Zaczerpnięte z Mathematics in 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
codelogic
źródło
2

Dla tego, który programował na Pycharmie, ożywia także innych.

 import operator
 Arr1=[1,2,3,45]
 Arr2=[3,4,56,78]
 print(list(map(operator.sub,Arr1,Arr2)))
Sahil Nagpal
źródło
1

Połączenie funkcji mapi lambdaw Pythonie jest dobrym rozwiązaniem tego rodzaju problemu:

a = [2,2,2]
b = [1,1,1]
map(lambda x,y: x-y, a,b)

zip funkcja jest kolejnym dobrym wyborem, jak pokazuje @UncleZeiv

BioCoder
źródło
0
arr1=[1,2,3]
arr2=[2,1,3]
ls=[arr2-arr1 for arr1,arr2 in zip(arr1,arr2)]
print(ls)
>>[1,-1,0]
ravi tanwar
źródło
2
Chociaż ten fragment kodu może być rozwiązaniem, dołączenie wyjaśnienia naprawdę pomaga poprawić jakość Twojego posta. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a osoby te mogą nie znać powodów, dla których zaproponowałeś kod.
Narendra Jadhav
0

Ta odpowiedź pokazuje, jak napisać „normalny / łatwo zrozumiały” kod Pythona.

Proponuję nie używać, zipponieważ tak naprawdę nie wszyscy o tym wiedzą.


Rozwiązania używają list składanych i typowych funkcji wbudowanych.


Alternatywa 1 (zalecana):

a = [2, 2, 2]
b = [1, 1, 1]
result = [a[i] - b[i] for i in range(len(a))]

Zalecane, ponieważ używa tylko najbardziej podstawowych funkcji w Pythonie


Alternatywa 2:

a = [2, 2, 2]
b = [1, 1, 1]
result = [x - b[i] for i, x in enumerate(a)]

Alternatywa 3 (jak wspomniano przez BioCoder ):

a = [2, 2, 2]
b = [1, 1, 1]
result = list(map(lambda x, y: x - y, a, b))
Timmy Chan
źródło
Dlaczego głos przeciw? Moja odpowiedź jest wyjątkowa i może być pomocna dla innych.
Timmy Chan,
-2

Spróbuj tego:

list(array([1,2,3])-1)
Rostyslav Dzinko
źródło