Tengo una lista anidada como esta que:
list = [[1,2,3], [2,5,7,6], [1,-1], [5,7], [6,3,7,4,3], [2, 5, 1, -5]]
Lo que intento hacer es eliminar listas anidadas, donde el valor dentro de estas listas es positivo y negativo. He intentado hacerlo por comprensión de la lista, pero no pude resolverlo.
def method(list):
return [obj for obj in list if (x for x in obj if -x not in obj)]
Los resultados obtenidos deben ser como:
list = [[1,2,3], [2,5,7,6], [5,7], [6,3,7,4,3]]
6 respuestas
Suponiendo que desea listas donde los elementos son negativos o positivos, puede usar la función predefinida all
para verificar ambas posibilidades
result = [L for L in x if all(y>0 for y in L) or all(y<0 for y in L)]
Editar:
En los comentarios aclaraste qué es una lista válida (por ejemplo, [-1, 2]
es válida) ... con esta nueva formulación, la prueba debería ser
result = [L for L in x if all(-y not in L for y in L)]
Donde cada prueba es ahora sin embargo cuadrática en el tamaño de la lista. Usando set
este problema puede eliminarse
result = [L for L in x if all(-y not in S for S in (set(L),) for y in L)]
Su generador debe ceder si se aplica la condición para filtrar un objeto.
Luego alimenta el generador a un agregador para determinar si obj debe ser filtrado.
el agregador podría ser cualquiera o todos, o algo diferente.
# assuming obj should be filtered if both x and the inverse of x are in obj
def method_with_all(src):
return [obj for obj in src if all(-x not in obj for x in obj)]
def method_with_any(src):
return [obj for obj in src if any(-x in obj for x in obj)]
Puede filtrar las listas que tienen elementos negativos y positivos:
def keep_list(nested_list):
is_first_positive = nested_list[0] > 0
for element in nested_list[1:]:
if (element > 0) != is_first_positive:
return False
return True
my_list = [[1,2,3], [2,5,7,6], [1,-1], [5,7], [6,3,7,4,3], [2, 5, 1, -5]]
print(list(filter(keep_list, my_list)))
Salida:
[[1, 2, 3], [2, 5, 7, 6], [5, 7], [6, 3, 7, 4, 3]]
Numpy también se puede usar. Mi solución aquí es similar a la operación "todos" sugerida por otros pero codificada explícitamente y solo necesita una condición. Comprueba si el signo de todos los elementos es igual al signo del primer elemento (también podría ser cualquier otro).
from numpy import *
def f(b):
return [a for a in b if sum(sign(array(a)) == sign(a[0])) == len(a)]
Para tu caso ...
data = [[1,2,3], [2,5,7,6], [1,-1], [5,7], [6,3,7,4,3], [2, 5, 1, -5]]
print(f(data))
... volverá:
[[1, 2, 3], [2, 5, 7, 6], [5, 7], [6, 3, 7, 4, 3]]
Usando la comprensión de la lista puedes hacer algo como:
def method2(list):
return [obj for obj in list if (all(n>0 for n in obj) or all(n<0 for n in obj))]
Que, con tu ejemplo, da como resultado:
[[1, 2, 3], [2, 5, 7, 6], [5, 7], [6, 3, 7, 4, 3]]
En general es mejor dividir la tarea por pasos:
- La lista dada encuentra los aspectos positivos (función
positives
) - En la lista dada, encuentre los negativos y multiplíquelos por -1 (función
negatives
) - Si la intersección de los positivos y negativos no está vacía, elimine.
Entonces, podrías hacer:
def positives(ls):
return set(l for l in ls if l > 0)
def negatives(ls):
return set(-1*l for l in ls if l < 0)
list = [[1, 2, 3], [2, 5, 7, 6], [1, -1], [5, 7], [6, 3, 7, 4, 3], [2, 5, 1, -5]]
result = [l for l in list if not negatives(l) & positives(l)]
print(result)
Salida
[[1, 2, 3], [2, 5, 7, 6], [5, 7], [6, 3, 7, 4, 3]]
Como nota al margen, no debe usar list como nombre de variable, ya que oculta la función de lista integrada.
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.