2010-04-24 14 views
5

Tratando de encontrar una forma eficiente de extraer todas las instancias de elementos en una matriz de otra.Uso de matrices con otras matrices en Python

Por ejemplo

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

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

matriz 1 es una serie de elementos que deben ser extraído fuera de la matriz 2. Por lo tanto, matriz de 2 debe ser modificado para ["456", "789"]

Yo sé cómo hacer esto, pero no de manera eficiente.

Respuesta

6

Estas son listas, no matrices. (La palabra "matriz" significa diferentes cosas para diferentes personas, pero en python los objetos se llaman listas, y eso es todo; hay otros módulos que proporcionan objetos que se llaman matrices, como array y numpy)

Para responder su pregunta, la forma más fácil es no modificar array2 en absoluto. Utilice una lista por comprensión:

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

(el conjunto hace que este O (n) en lugar de O (n^2))

Si es absolutamente necesidad matriz2 mutar (ya que existe en otras partes), se puede usar la asignación de división:

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

Es igual de eficiente, pero desagradable.

edit: como señala Mark Byers, esto solo funciona si array1 solo contiene elementos hashable (como cadenas, números, etc.).

+2

Si no le importan los duplicados o el pedido, debería considerar hacer 'set (array2) - set (array2)'. – Jules

3

Si sus listas no pueden contener duplicados y no le importa el orden, entonces debe utilizar conjuntos en lugar de listas (por cierto, se les llama listas, no matrices). A continuación, lo que quiere es a la vez rápido y trivial de implementar:

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

Si lista2 puede contener duplicados o las cuestiones de orden entonces usted todavía puede hacer lista1 un conjunto para acelerar las operaciones de búsqueda:

>>> 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 que esto requiere que los elementos sean manejables, pero que se ejecuten cerca del tiempo O (n).

Si los artículos no se pueden cargar pero se pueden ordenar, se puede ordenar la lista1 y usar una búsqueda binaria para encontrar los artículos en ella. Esto le da a O (n log (n)) tiempo.

Si sus artículos no son lavables ni pueden pedirse, tendrá que recurrir a la búsqueda lineal simple O (n * n) lenta para cada elemento.

+0

Y si no le importa el orden. –

+0

No ... no quiero la diferencia entre los dos. Si bien no es el escenario exacto ... cosa de la matriz 1 como una lista de palabras malas, la matriz dos como una lista de palabras de búsqueda. Quiero obtener un resultado de las palabras de búsqueda con todas las palabras malas de una lista maestra en el conjunto 1 eliminado. – Scott

+0

@Thomas: Gracias, he incluido ese punto en mi respuesta. –

0

La manera directa sería algo así como;

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

listas por comprensión es lo que necesita aquí