Tengo una lista que es una lista multi bidimensional. Básicamente me gustaría crear una variable con los duplicados en cada fila y luego me gustaría crear otra variable sin duplicados en cada fila. ¿Se puede hacer esto usando una lista de comprensión?

df = [[[2, 3, 3, 3, 7, 8, 9, 9],[3, 3, 3, 5, 9, 9, 10, 11],[3, 3, 3, 4, 9, 9, 13, 15]],
      [[2, 3, 3, 3, 4, 4, 5, 6],[4, 4, 5, 7, 7, 7, 8, 10],[4, 4, 6, 7, 7, 7, 9, 11],[3, 3, 3, 4, 4, 8, 11, 12]],
      [[4, 6, 7, 7, 7, 9, 11, 11],[3, 3, 3, 5, 9, 10, 11, 11],[3, 3, 3, 6, 7, 7, 7, 10, 12, 12]]]

Me gustaría que mi resultado sea:

Dup = [[[3,9],[3, 9],[3, 9]],[[3, 4],[4, 7],[4, 7,[3, 4]],[[7, 11],[3, 11],[3, 7, 12]]]

Not in = [[[2 7, 8],[5,10, 11],[4, 13, 15]],[[2, 5, 6],[5,8, 10],[6, 9, 11],[8, 11, 12]],[[4, 6, 9],[5, 9, 10],[6,10]]]

0
Chris88 30 sep. 2019 a las 18:05

3 respuestas

La mejor respuesta

Esto se puede lograr utilizando listas de comprensión y collections.Counter de la siguiente manera:

dup = [[[i for i, c in Counter(sl).items() if c>1] for sl in l] for l in df]
not_in = [[[i for i, c in Counter(sl).items() if c==1] for sl in l] for l in df]

Solo digo que usé l y sl las listas y sublistas en consecuencia. i representa el elemento y c es el recuento de ese elemento en sl. Los resultados son los siguientes:

#duplicates
[[[3, 9], [3, 9], [3, 9]], [[3, 4], [4, 7], [4, 7], [3, 4]], [[7, 11], [3, 11], [3, 7, 12]]]
#uniques
[[[2, 7, 8], [5, 10, 11], [4, 13, 15]], [[2, 5, 6], [5, 8, 10],[6, 9, 11], [8, 11, 12]], [[4, 6, 9], [5, 9, 10], [6, 10]]]
3
Jab 30 sep. 2019 a las 15:51

Sin importaciones adicionales, solo usando una comprensión de lista doblemente anidada, set y count:

>>> [[[x for x in set(ll) if ll.count(x) > 1] for ll in l] for l in df]
[[[3, 9], [3, 9], [3, 9]],
 [[3, 4], [4, 7], [4, 7], [3, 4]],
 [[7, 11], [3, 11], [3, 7, 12]]]

>>> [[[x for x in set(ll) if ll.count(x) == 1] for ll in l] for l in df]
[[[2, 7, 8], [5, 10, 11], [4, 13, 15]],
 [[2, 5, 6], [5, 8, 10], [6, 9, 11], [8, 11, 12]],
 [[4, 6, 9], [5, 9, 10], [6, 10]]]

Sin embargo, tenga en cuenta que usar Counter podría ser más rápido si las listas más internas son muy grandes; de lo contrario, no debería importar, y esta versión podría ser la más sencilla y fácil de leer.

2
tobias_k 30 sep. 2019 a las 15:45
Dup = [[list(dict.fromkeys([el for i, el in zip(range(len(l)), l) if el in l[:i]+l[i+1:]])) for l in ll] for ll in df]
Not_in = [[[el for i, el in zip(range(len(l)), l) if el not in l[:i]+l[i+1:]] for l in ll] for ll in df]
1
Tommaso Sgarbanti 30 sep. 2019 a las 15:46
58170598