Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

217
Vistas
Obtener rangos donde los valores no son Ninguno

La meta

Me gustaría obtener los rangos donde los valores no son Ninguno en una lista, por ejemplo:

 test1 = [None, 0, None] test2 = [2,1,None] test3 = [None,None,3] test4 = [1,0,None,0,0,None,None,1,None,0] res1 = [[1,1]] res2 = [[0,1]] res3 = [[2,2]] res4 = [[0,1],[3,4],[7,7],[9,9]]

lo que he probado

Esta es mi implementación súper larga, que no funciona perfectamente...

 def get_not_None_ranges(list_): # Example [0, 2, None, 1, 4] -> [[0, 1], [3, 4]] r = [] end_i = len(list_)-1 if list_[0] == None: s = None else: s = 0 for i, elem in enumerate(list_): if s != None: if elem == None and end_i != i: r.append([s,i-1]) s = i+1 if end_i == i: if s > i: r=r elif s==i and elem == None: r=r else: r.append([s,i]) else: if elem != None: s = i if end_i == i: if s > i: r=r else: r.append([s,i]) return r

Como puede ver, los resultados a veces son incorrectos:

 print(get_not_None_ranges(test1)) print(get_not_None_ranges(test2)) print(get_not_None_ranges(test3)) print(get_not_None_ranges(test4)) [[1, 2]] [[0, 2]] [[2, 2]] [[0, 1], [3, 4], [6, 5], [7, 7], [9, 9]]

Entonces, me preguntaba si ustedes conocen una forma mucho mejor de lograr esto.

over 4 years ago · Santiago Trujillo
9 Respuestas
Responde la pregunta

0

Solo necesita iterar sobre la lista y verificar dos condiciones:

  1. Si el elemento anterior es None y el elemento actual no es None , comience un nuevo "rango".
  2. Si el elemento anterior no es None y el elemento actual es None , finaliza el rango actualmente activo en el índice anterior.
 def gnnr(lst): all_ranges = [] current_range = [] prev_item = None for index, item in enumerate(lst): # Condition 1 if prev_item is None and item is not None: current_range.append(index) # Condition 2 elif prev_item is not None and item is None: current_range.append(index - 1) # Close current range at the previous index all_ranges.append(current_range) # Add to all_ranges current_range = [] # Reset current_range prev_item = item # If current_range isn't closed, close it at the last index of the list if current_range: current_range.append(index) all_ranges.append(current_range) return all_ranges

Llamar a esta función con sus casos de prueba da el resultado esperado:

 [[1, 1]] [[0, 1]] [[2, 2]] [[0, 1], [3, 4], [7, 7], [9, 9]]
over 4 years ago · Santiago Trujillo Denunciar

0

Darle una oportunidad. El código usa Type Hint y una tupla con nombre para aumentar la legibilidad.

 from typing import NamedTuple,List,Any class Range(NamedTuple): left: int right: int def get_ranges(lst: List[Any]) -> List[Range]: ranges : List[Range] = [] left = None right = None for i,x in enumerate(lst): is_none = x is None if is_none: if left is not None : right = right if right is not None else left ranges.append(Range(left,right)) left = None right = None else: if left is None: left = i else: right = i if left is not None: right = right if right is not None else left ranges.append(Range(left,right)) return ranges data = [[1,0,None,0,0,None,None,1,None,0],[None,None,3],[2,1,None],[None, 0, None]] for entry in data: print(get_ranges(entry))

salida

 [Range(left=0, right=1), Range(left=3, right=4), Range(left=7, right=7), Range(left=9, right=9)] [Range(left=2, right=2)] [Range(left=0, right=1)] [Range(left=1, right=1)]
over 4 years ago · Santiago Trujillo Denunciar

0

Utilice itertools.groupby :

 from itertools import groupby test1 = [None, 0, None] test2 = [2, 1, None] test3 = [None, None, 3] test4 = [1, 0, None, 0, 0, None, None, 1, None, 0] def get_not_None_ranges(lst): result = [] for key, group in groupby(enumerate(lst), key=lambda x: x[1] is not None): if key: index, _ = next(group) result.append([index, index + sum(1 for _ in group)]) return result print(get_not_None_ranges(test1)) print(get_not_None_ranges(test2)) print(get_not_None_ranges(test3)) print(get_not_None_ranges(test4))

Producción

 [[1, 1]] [[0, 1]] [[2, 2]] [[0, 1], [3, 4], [7, 7], [9, 9]]
over 4 years ago · Santiago Trujillo Denunciar

0

Bueno, podemos resolver esto usando el enfoque clásico de ventana deslizante.

Aquí está la solución que funciona bien:

 def getRanges(nums): left = right = 0 ranges, n = [], len(nums) while right < n: while left < n and nums[left] == None: left += 1 right += 1 while right < n and nums[right] != None: right += 1 if right >= n: break ranges.append([left, right - 1]) left = right = right + 1 return ranges + [[left, right - 1]] if right - 1 >= left else ranges

Vamos a probarlo:

 test = [ [1, 0, None, 0, 0, None, None, 1, None, 0], [None, None, 3], [2, 1, None], [None, 0, None], ] for i in test: print(getRanges(i))

Producción:

 [[0, 1], [3, 4], [7, 7], [9, 9]] [[2, 2]] [[0, 1]] [[1, 1]]
over 4 years ago · Santiago Trujillo Denunciar

0

Qué tal si:-

 test1 = [None, 0, None] test2 = [2, 1, None] test3 = [None, None, 3] test4 = [1, 0, None, 0, 0, None, None, 1, None, 0] def goal(L): r = [] _r = None for i, e in enumerate(L): if e is not None: if _r: _r[1] = i else: _r = [i, i] else: if _r: r.append(_r) _r = None if _r: r.append(_r) return r for _l in [test1, test2, test3, test4]: print(goal(_l))
over 4 years ago · Santiago Trujillo Denunciar

0

Usando el primero y el último de cada grupo de no ninguno:

 from itertools import groupby def get_not_None_ranges(lst): result = [] for nones, group in groupby(enumerate(lst), lambda x: x[1] is None): if not nones: first = last = next(group) for last in group: pass result.append([first[0], last[0]]) return result
over 4 years ago · Santiago Trujillo Denunciar

0

Aquí está mi ejemplo. Definitivamente NO es la forma más eficiente, pero creo que es más intuitiva y puedes optimizarla más adelante.

 def get_not_None_ranges(list_: list): res = [] start_index = -1 for i in range(len(list_)): e = list_[i] if e is not None: if start_index < 0: start_index = i else: if start_index >= 0: res.append([start_index, i - 1]) start_index = -1 if start_index >= 0: res.append([start_index, len(list_) - 1]) return res

El pensamiento principal de esta función:

  1. start_index se inicializa con -1
  2. Cuando no nos encontremos con el elemento Ninguno, establezca start_index en su índice
  3. Cuando nos encontremos con Ninguno, guarde [start_index, i - 1 (ya que el elemento anterior es el final de la sesión)]. A continuación, establezca start_index de nuevo en -1.
  4. Cuando nos encontramos con None pero start_index es -1, no necesitamos hacer nada ya que no hemos encontrado el elemento not None este turno. Por la misma razón, no haga nada cuando nos encontremos con no Ninguno cuando start_index > 0.
  5. Cuando el bucle finaliza pero start_index sigue siendo mayor que 0, significa que no hemos registrado este turno válido. Así que tenemos que hacer eso manualmente.

Creo que puede ser un poco complejo, puede ayudar pegar el código anterior y depurarlo línea por línea en un depurador.

over 4 years ago · Santiago Trujillo Denunciar

0

Una solución no groupby que no necesita un tratamiento adicional para el último grupo:

 def get_not_None_ranges(lst): result = [] it = enumerate(lst) for i, x in it: if x is not None: first = last = i for i, x in it: if x is None: break last = i result.append([first, last]) return result

Cada vez que encuentro el primero de una racha que no es Ninguno, uso un bucle interno para ejecutar de inmediato hasta el último de esa racha. Para permitir que ambos bucles usen el mismo iterador, lo almaceno en una variable.

over 4 years ago · Santiago Trujillo Denunciar

0

Otra solución (una sola línea con itertools.groupby ):

 from itertools import groupby out = [[(v := list(g))[0][1], v[-1][1]] for _, g in groupby(enumerate(i for i, v in enumerate(testX) if not v is None), lambda k: k[0] - k[1],)]

Pruebas:

 test1 = [None, 0, None] test2 = [2, 1, None] test3 = [None, None, 3] test4 = [1, 0, None, 0, 0, None, None, 1, None, 0] tests = [test1, test2, test3, test4] for t in tests: out = [ [(v := list(g))[0][1], v[-1][1]] for _, g in groupby( enumerate(i for i, v in enumerate(t) if not v is None), lambda k: k[0] - k[1], ) ] print(out)

Huellas dactilares:

 [[1, 1]] [[0, 1]] [[2, 2]] [[0, 1], [3, 4], [7, 7], [9, 9]]
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda