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

255
Vistas
Quiero eliminar todas las listas con longitud 1 al principio y al final pero no en el medio en python

Dada una lista de listas (es decir, una lista anidada), quiero eliminar todas las listas internas con longitud 1 desde el principio y el final de la lista externa. Por ejemplo

d = [[3], [1,5], [3], [3,2,4], [8], [3]] debe convertirse en: [1,5], [3], [3,2,4] .

Para el comienzo de la lista, estoy usando el siguiente código:

 i = 0 while len(d[i]) == 1: d.remove(d[i]) n = n -1

y para el final, uso este código:

 while len(d[n-1]) == 1: d.remove(d[n-1]) n = n - 1

donde n = número de listas.

Cuando ejecuto esto me sale:

 [[1, 5], [3, 2, 4]]

Entonces también elimina las listas en el medio con longitud 1. ¿Cómo puedo cambiar el código para que no haga eso?

Entonces, para un número n de listas, quiero eliminar todas las listas del principio que tengan una longitud de 1 hasta que haya una lista que no tenga una longitud de 1. Quiero hacer lo mismo para el final de la lista.

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

0

La mayoría de las respuestas actuales implican aparecer repetidamente desde el principio de una lista, lo cual es lento.

Usando las respuestas aquí para encontrar el primer y último índice donde una condición no se cumple, podemos encontrar el inicio y el final de la sublista deseada en tiempo lineal. Luego, construimos la rebanada usando los índices inicial y final encontrados. Si la lista contiene solo sublistas de longitud 1, entonces nuestros generadores generarán una StopIteration ; para evitar esto, verificamos con anticipación si todas las listas tienen longitud 1:

 if all(len(item) == 1 for item in data): result = [] else: start = next(i for i, v in enumerate(data) if len(v) != 1) end = len(data) - next(i for i, v in enumerate(reversed(data)) if len(v) != 1) result = data[start:end] print(result)

Esto da como resultado:

 [[1, 5], [3], [3, 2, 4]]

Si realmente necesita velocidad, puede omitir los generadores y la verificación de primer paso (este código ha sido mejorado a partir de una sugerencia de juanpa.arrivillaga ):

 start = -1 for idx in range(len(data)): if len(data[idx]) != 1: start = idx break end = len(data) for idx in reversed(range(len(data))): if len(data[idx]) != 1: end = idx break result = data[start:end + 1] print(result)

que parece funcionar mejor en mi máquina.

Código de referencia:

 import timeit def bb1(data): if all(len(item) == 1 for item in data): result = [] else: start = next(i for i, v in enumerate(data) if len(v) != 1) end = len(data) - next(i for i, v in enumerate(reversed(data)) if len(v) != 1) result = data[start:end] return result def bb2(data): start = -1 for idx in range(len(data)): if len(data[idx]) != 1: start = idx break end = len(data) for idx in reversed(range(len(data))): if len(data[idx]) != 1: end = idx break result = data[start:end + 1] return result def fb(d): while len(d[0]) == 1: d.pop(0) # remove from head while len(d[-1]) == 1: d.pop() # remove from tail

Entonces,

 data = ([[3] for _ in range(100000)]) + [[3], [1,5], [3], [3,2,4], [8], [3]] %timeit -n7 bb1(data[:]) %timeit -n7 bb2(data[:]) %timeit -n7 fb(data[:])

Producción:

 7 loops, best of 5: 23.7 ms per loop 7 loops, best of 5: 13.1 ms per loop 7 loops, best of 5: 900 ms per loop
over 4 years ago · Santiago Trujillo Denunciar

0

Simplemente puede realizar un seguimiento de los índices donde se cumple la condición y luego dividir su lista en consecuencia, en lugar de modificar la lista.

 def filter_list(list_of_list, len_to_filter): l, r = 0, -1 # left, right indices while len(list_of_list[l]) == len_to_filter: l += 1 while len(list_of_list[r]) == len_to_filter: r -= 1 if r == -1: # avoid case where r + 1 is 0 return list_of_list[l:] else: return list_of_list[l : r + 1] filter_list(d, 1)

Esto no modifica la lista original y no requiere ninguna ordenación o inversión. Simplemente recorre la lista de cada lado hasta que se alcanza un tamaño diferente al esperado.

Aquí hay un punto de referencia que lo compara con pop , si hay pocas listas con la longitud requerida para eliminar, la version y las versiones de índices son prácticamente las mismas. Si hay muchas listas con la longitud requerida para filtrar, las operaciones pop se vuelven no despreciables y la versión de índices es mejor.

 import random small = [[3], [1, 5], [3], [3, 2, 4], [8], [3]] # create 10_000 lists of length 1 or 2 ll = [ [random.randint(0, 1000) for _ in range(random.randint(1, 2))] for _ in range(10_000) ] worst_case = [ [random.randint(0, 1000) for _ in range(random.randint(1, 1))] for _ in range(10_000) ] worst_case[5000] = [1, 2, 3] def filter_pop(list_of_list, len_to_filter): while len(list_of_list[0]) == len_to_filter: list_of_list.pop(0) while len(list_of_list[-1]) == len_to_filter: list_of_list.pop() return list_of_list def filter_list(list_of_list, len_to_filter): l, r = 0, -1 # left, right indices while len(list_of_list[l]) == len_to_filter: l += 1 while len(list_of_list[r]) == len_to_filter: r -= 1 if r == -1: # avoid case where r + 1 is 0 return list_of_list[l:] else: return list_of_list[l : r + 1]
 In [208]: %timeit -n100 filter_pop(ll[:], 1) 47.6 µs ± 9.77 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) In [209]: %timeit -n100 filter_pop(worst_case[:], 1) 7.46 ms ± 71.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) In [210]: %timeit -n100 filter_list(ll, 1) 43.7 µs ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) In [211]: %timeit -n100 filter_list(worst_case, 1) 1 ms ± 59 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
over 4 years ago · Santiago Trujillo Denunciar

0

aquí hay una solución simple:

 def removeFunction(d): l = 0 r = len(d) - 1 # remove length 1 elements from beginning for i in range(len(d)): if len(d[i]) > 1: l = i break # remove length 1 elements from the end for i in range(len(d)-1, -1, -1): if len(d[i]) > 1: r = i break return d[l:r+1]
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