[Python-es] obtener diferencias entre elementos de dos listas de listas.

Rolando Espinoza La Fuente darkrho en gmail.com
Vie Mar 5 16:50:58 CET 2010


Esta solución es específica para el ejemplo que diste:

# salida
[1, 1, 2] [2, 1, 6] [0, 2]
[2, 3, 5] [1, 3, 5] [0]
[] [4, 4, 7] [0, 1, 2]

# parte relevante
    L1 = [[1, 1, 2], [2, 3, 5], [3, 2, 8]]
    L2 = [[2, 1, 6], [3, 2, 8], [1, 3, 5], [4, 4, 7]]

    clean(L1, L2)

    for i in range(max(len(L1), len(L2))):
        a = getitem(L1, i, [])
        b = getitem(L2, i, [])
        diff = []

        for j in range(max(len(a), len(b))):
            if not getitem(a, j) == getitem(b, j):
                diff.append(j)

        print a, b, diff

Pero dudo que sea la más optima, el código completo aqui:
http://gist.github.com/322839

No te preocupes, que todos aprendemos algo :)

Pensaba utilizar sets, pero el problema es que te ordena los elementos
y simplifica los comunes
set([3,2,1]) -> (1,2,3)
set([2,2,2]) -> (2)Serviría para comparar elementos, pero pierdes los índices.

Rolando



2010/3/5 Boris Perez Canedo <inf200523 en ucf.edu.cu>:
>> El 05/03/10 09:36, Boris Perez Canedo escribió:
>>> Hola a todos.
>>>
>>> Viendo los comentarios relacionados con "Buscar índices de un array (que
>>> cumple condición) de forma eficiente" y el analisis profundo que este
>>> genero, me dio un poco de verguenza respecto a un problema que se me
>>> presento y del cual, incluso antes de leer estos comentarios, sabia que
>>> la solucion que habia propuesto no era eficiente ni mucho menos
>>> "elegante", pero bueno lo de elegante se lo puedo achacar a mi falta de
>>> experiencia con Python o tambien puede ser que la falta de elegancia
>>> genere la ineficiencia.
>>>
>>> No pongo mi solucion porque me da tremenda pena!
>>>
>>> Mi problema:
>>> Encontrar las diferencias entre los elementos de dos listas de listas
>>> cuyos elementos (listas) comparten entre si un elemento comun en una
>>> posicion dada.
>>> Disculpen el enredo espero entiendan mejor con lo siguiente:
>>>
>>> Entrada:
>>> en ste caso el elemento considerado comun se encuentra en la posicion 1
>>>
>>> L1 = [ [ 1, 1, 2] , [ 2, 3, 5 ] , [ 3, 2, 8 ] ]
>>>
>>> L2 = [ [ 2, 1, 6 ], [ 3, 2, 8 ], [ 1, 3, 5 ], [ 4, 4, 7] ]
>>>
>>> Salida:
>>> [ (element1 , element2, diferencia),... ]
>>>
>>> la diferencia contiene los indices donde ambos elementos difieren.
>>>
>>>
>>> [ ( [ 1, 1, 2 ], [ 2, 1, 6 ], [ 0, 2 ] ), ([ 2, 3, 5 ], [ 1, 3, 5 ], [ 0
>>> ] ), ( [ ], [ 4, 4, 7 ], [ 0, 1, 2 ] ) ]
>>>
>>> Aclarar que en ningun caso, tanto las listas de entrada como la de
>>> salida, tienen obligatoriamente que estar ordenadas, pero si facilita la
>>> solucion o implica una mejora en la eficiencia pueden ser ordenadas.
>>>
>>>
>>>
>>> Gracias de antemano.
>>>
>>>
>>> Saludos,
>>> Boris.
>>
>
> Hola,
>
> Ok, me convencieron, pero les advierto que esta de piedra, por asi decirlo.
>
> def compare(L1, L2):
>     if len(L1) <> len(L2):
>         return None
>     else:
>         differ = []
>         for pos in range(len(L1)):
>             if L1[pos] <> L2[pos]:
>                 differ.append(pos)
>         return differ
>
> def FindDifferences(L1, L2, fixedPos):
>
>     not_in_L1 = []
>     not_in_L2 = []
>     for element2 in L2:
>         if element2 not in L1:
>             not_in_L1.append(element2)
>     for element1 in L1:
>         if element1 not in L2:
>             not_in_L2.append(element1)
>     differences = []
>
>     if len(not_in_L1) >= len(not_in_L2):
>         for pos in range(len(not_in_L1)):
>             found = False
>             for pos1 in range(len(L1)):
>                 if not_in_L1[pos][fixedPos] == L1[pos1][fixedPos]:
>                     found = True
>                     now = not_in_L1[pos]
>                     before = L1[pos1]
>                     diff = compare(now, before)
>                     if diff <> []:
>                         differences.append((now, before, diff))
>                     break
>             if not found:
>                 differences.append((not_in_L1[pos], [], [-1]))
>     else:
>          for pos in range(len(not_in_L2)):
>             found = False
>             for pos2 in range(len(L2)):
>                 if not_in_L2[pos][fixedPos] == L2[pos2][fixedPos]:
>                     found = True
>                     before = not_in_L2[pos]
>                     now = L2[pos2]
>                     diff = compare(now, before)
>                     if diff <> []:
>                         differences.append((now, before, diff))
>                     break
>             if not found:
>                 differences.append(([], not_in_L2[pos], [-1]))
>
>
>     return differences
>
> Lo que mas me molesta de esta solucion es que tengo que repetir codigo
> (aparece en el if else)
>
> Gracias y no me tiren piedras!
>
> Ah, otra cosa, interpretese L1 y L2 como: L1 obtenido de una base datos y L2
> como: informacion actual que se desea compara con L1.
>
> Saludos,
> Boris.
>
> ________________________________
>
> La mejor vacuna contra el virus A(H1N1) es la higiene personal
>
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> http://mail.python.org/mailman/listinfo/python-es
> FAQ: http://python-es-faq.wikidot.com/
>
>


Más información sobre la lista de distribución Python-es