Sottraendo 2 elenchi in Python


86

In questo momento ho i valori vector3 rappresentati come elenchi. c'è un modo per sottrarre 2 di questi valori come vector3, come

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

Dovrei usare le tuple?

Se nessuno di loro definisce questi operandi su questi tipi, posso definirlo invece?

In caso contrario, dovrei creare una nuova classe vector3?

Risposte:


135

Se questo è qualcosa che finisci per fare frequentemente e con operazioni diverse, dovresti probabilmente creare una classe per gestire casi come questo, o meglio usare qualche libreria come Numpy .

Altrimenti, cerca le liste di comprensione usate con la funzione integrata zip :

[a_i - b_i for a_i, b_i in zip(a, b)]

83

Ecco un'alternativa alla comprensione delle liste. Map esegue l'iterazione delle liste (gli ultimi argomenti), facendolo simultaneamente, e passa i loro elementi come argomenti alla funzione (il primo argomento). Restituisce l'elenco risultante.

import operator
map(operator.sub, a, b)

Questo codice perché ha meno sintassi (che è più estetico per me), e apparentemente è il 40% più veloce per elenchi di lunghezza 5 (vedi il commento di bobince). Tuttavia, entrambe le soluzioni funzioneranno.


Di solito vedo che le comprensioni degli elenchi vengono consigliate su map (), anche se potrebbe essere solo perché è un codice dall'aspetto più pulito ... non sono sicuro della differenza di prestazioni, se presente.
David Z,

2
La map () risulta quasi il 40% più veloce per me su Py2.6 per una sottrazione di cinque elementi. Le comprensioni sono più nuove e più pulite dove evitano un lambda, ma per mappare le funzioni esistenti la mappa può ancora essere carina ... specialmente qui dove puoi sfruttare lo zip integrato.
bobince

1
questo funziona anche per array.array (sebbene il risultato sia una lista)
gens

6
è necessaria la clausola "operatore di importazione"; int .__ sub__ fa meglio il trucco))
garej

13

Se le tue liste sono aeb, puoi fare:

map(int.__sub__, a, b)

Ma probabilmente non dovresti. Nessuno saprà cosa significa.


1
Ci sono andato io stesso con i galleggianti. In tal caso map(float.__sub__, a, b)funziona. Grazie per il consiglio!
S3DEV

9

Dovrei raccomandare NumPy pure

Non solo è più veloce per eseguire calcoli vettoriali, ma ha anche un sacco di funzioni utili.

Se vuoi qualcosa di ancora più veloce per i vettori 1d, prova vop

È simile a MatLab, ma gratuito e roba del genere. Ecco un esempio di cosa faresti

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

Boom.


1
np.arraysarebbe una soluzione più semplice
garej

6

Se hai due elenchi chiamati "a" e "b", puoi fare: [m - n for m,n in zip(a,b)]



4

Una classe Vector leggermente diversa.

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)

3

Se prevedi di eseguire più di semplici battute, sarebbe meglio implementare la tua classe e sovrascrivere gli operatori appropriati quando si applicano al tuo caso.

Tratto da 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

2

Per chi era abituato a programmare su Pycharm, ne ravviva anche altri.

 import operator
 Arr1=[1,2,3,45]
 Arr2=[3,4,56,78]
 print(list(map(operator.sub,Arr1,Arr2)))

1

La combinazione di mape lambdafunzioni in Python è una buona soluzione per questo tipo di problema:

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

zip la funzione è un'altra buona scelta, come dimostrato da @UncleZeiv


0
arr1=[1,2,3]
arr2=[2,1,3]
ls=[arr2-arr1 for arr1,arr2 in zip(arr1,arr2)]
print(ls)
>>[1,-1,0]

2
Sebbene questo snippet di codice possa essere la soluzione, includere una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e quelle persone potrebbero non conoscere i motivi del tuo suggerimento sul codice.
Narendra Jadhav

0

Questa risposta mostra come scrivere codice pitonico "normale / facilmente comprensibile".

Suggerisco di non utilizzarlo zipperché non tutti lo sanno.


Le soluzioni utilizzano le comprensioni degli elenchi e le funzioni incorporate comuni.


Alternativa 1 (consigliata):

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

Consigliato in quanto utilizza solo le funzioni di base in Python


Alternativa 2:

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

Alternativa 3 (come menzionato da BioCoder ):

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

Perché il voto negativo? La mia risposta è unica e può essere di aiuto agli altri.
Timmy Chan

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.