2010-04-24 12 views
5

Provare a trovare un modo efficiente per estrarre tutte le istanze di elementi in una matrice da un'altra.Uso di array con altri array in Python

Ad esempio

array1 = ["abc", "def", "ghi", "jkl"] 

array2 = ["abc", "ghi", "456", "789"] 

Array 1 è un array di elementi che devono essere estratti su matrice 2. Così, matrice 2 deve essere modificato per ["456", "789"]

so come fare questo, ma no in maniera efficiente.

risposta

6

Questi sono elenchi, non matrici. (La parola "allineamento" significa cose diverse per persone diverse, ma in Python gli oggetti stessi elenchi delle chiamate, e questo è tutto, ci sono altri moduli che forniscono oggetti che si definiscono gli array, come array e numpy)

Per rispondere la tua domanda, il modo più semplice è di non modificare affatto array2. Utilizzare una lista di comprensione:

set1 = set(array1) 
array2 = [e for e in array2 if e not in set1] 

(l'insieme rende questo O (n) invece di O (n^2))

Se è assolutamente must mutare array2 (perché esiste altrove), è può utilizzare l'assegnazione delle porzioni:

array2[:] = [e for e in array2 if e not in set1] 

È altrettanto efficiente, ma piuttosto brutto.

modifica: come sottolinea Mark Byers, funziona solo se array1 contiene solo elementi (come stringhe, numeri, ecc.).

+2

Se non ti preoccupi dei duplicati o dell'ordine, dovresti prendere in considerazione 'set (array2) - set (array2)'. – Jules

3

Se i tuoi elenchi non possono contenere duplicati e non ti interessa l'ordine, dovresti usare set anziché elenchi (a proposito, sono chiamati elenchi, non array). Allora ciò che si vuole è sia veloce e banale da implementare:

>>> set1 = set(["abc", "def", "ghi", "jkl"]) 
>>> set2 = set(["abc", "ghi", "456", "789"]) 
>>> set2 - set1 
set(['456', '789']) 

Se lista2 possono contenere i duplicati o le questioni di ordine allora si può ancora fare lista1 un set per accelerare le ricerche:

>>> list1 = ["abc", "def", "ghi", "jkl"] 
>>> list2 = ["abc", "ghi", "456", "789"] 
>>> set1 = set(list1) 
>>> [a for a in list2 if a not in set1] 
['456', '789'] 

Nota questo richiede che gli oggetti siano lavabili ma che scorrono vicino al tempo O (n).

Se gli articoli non sono lavabili ma sono ordinabili, è possibile ordinare la lista1 e utilizzare una ricerca binaria per trovare gli elementi in essa contenuti. Questo dà il tempo O (n log (n)).

Se i tuoi articoli non sono né lavabili e non ordinabili, dovrai ricorrere alla ricerca lineare semplice O (n * n) per ciascun elemento.

+0

E se non si cura di ordine. –

+0

No. Non voglio la differenza tra i due. Mentre non è lo scenario esatto ... cosa di array 1 come elenco di parolacce, array due come elenco di parole chiave. Voglio ottenere un risultato delle parole di ricerca con tutte le parolacce da un elenco principale nell'array 1 rimosso. – Scott

+0

@Thomas: Grazie, ho incluso questo punto nella mia risposta. –

0

Il modo semplice sarebbe qualcosa di simile;

array2 = [i for i in array2 if i not in array1] 

list comprehension è quello che serve qui