una tuplas tamaño sirve que print para lista leer intercambiar guardar elementos como cargar python list

tuplas - print lista python



Divida una lista en partes basada en un conjunto de índices en Python (9)

Aquí hay otra respuesta.

def partition(l, indexes): result, indexes = [], indexes+[len(l)] reduce(lambda x, y: result.append(l[x:y]) or y, indexes, 0) return result

Es compatible con índices negativos y tal.

>>> partition([1,2,3,4,5], [1, -1]) [[1], [2, 3, 4], [5]] >>>

¿Cuál es la mejor manera de dividir una lista en partes en base a un número arbitrario de índices? Por ejemplo, dado el código a continuación

indexes = [5, 12, 17] list = range(20)

devolver algo como esto

part1 = list[:5] part2 = list[5:12] part3 = list[12:17] part4 = list[17:]

Si no hay índices, debe devolver la lista completa.


Cide''s hace tres copias de la matriz: [0] + copias de índices, ([0] + índices) + [] copias nuevamente, e índices [: - 1] copiarán una tercera vez. Il-Bhima hace cinco copias. (No estoy contando el valor de retorno, por supuesto).

Esos podrían reducirse (izip, islice), pero aquí hay una versión de copia cero:

def iterate_pairs(lst, indexes): prev = 0 for i in indexes: yield prev, i prev = i yield prev, len(lst) def partition(lst, indexes): for first, last in iterate_pairs(lst, indexes): yield lst[first:last] indexes = [5, 12, 17] lst = range(20) print [l for l in partition(lst, indexes)]

Por supuesto, las copias de matriz son bastante baratas (código nativo) en comparación con Python interpretado, pero esto tiene otra ventaja: es fácil de reutilizar, para mutar los datos directamente:

for first, last in iterate_pairs(lst, indexes): for i in range(first, last): lst[i] = first print lst # [0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 12, 12, 12, 12, 12, 17, 17, 17]

(Es por eso que pasé índices a iterate_pairs. Si no te importa eso, puedes eliminar ese parámetro y simplemente tener la línea final "yield prev, None", que es todo lo que necesita la partición ().)


El plural del índice es índices. Buscando simplicidad / legibilidad.

indices = [5, 12, 17] input = range(20) output = [] for i in reversed(indices): output.append(input[i:]) input[i:] = [] output.append(input) while len(output): print output.pop()


Esta es la solución más simple y más pitonisa que puedo pensar:

def partition(alist, indices): return [alist[i:j] for i, j in zip([0]+indices, indices+[None])]

si las entradas son muy grandes, entonces la solución de los iteradores debería ser más conveniente:

from itertools import izip, chain def partition(alist, indices): pairs = izip(chain([0], indices), chain(indices, [None])) return (alist[i:j] for i, j in pairs)

y, por supuesto, la solución de tipo muy, muy perezosa (si no te importa obtener matrices en lugar de listas, pero de todos modos siempre puedes revertirlas a listas):

import numpy partition = numpy.split


Esto es todo lo que pude pensar

def partition(list_, indexes): if indexes[0] != 0: indexes = [0] + indexes if indexes[-1] != len(list_): indexes = indexes + [len(list_)] return [ list_[a:b] for (a,b) in zip(indexes[:-1], indexes[1:])]


Me interesaría ver una manera más pitonica de hacer esto también. Pero esta es una solución horrible. Debería agregar una verificación para una lista de índice empírica.

Algo como:

indexes = [5, 12, 17] list = range(20) output = [] prev = 0 for index in indexes: output.append(list[prev:index]) prev = index output.append(list[indexes[-1]:]) print output

produce

[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19]]


Mi solución es similar a la de Il-Bhima.

>>> def parts(list_, indices): ... indices = [0]+indices+[len(list_)] ... return [list_[v:indices[k+1]] for k, v in enumerate(indices[:-1])]

Enfoque alternativo

Si está dispuesto a cambiar ligeramente la forma de ingresar índices, desde índices absolutos hasta relativos (es decir, desde [5, 12, 17] hasta [5, 7, 5] , lo que sigue también le dará la salida deseada, mientras que no crea listas intermedias.

>>> from itertools import islice >>> def parts(list_, indices): ... i = iter(list_) ... return [list(islice(i, n)) for n in chain(indices, [None])]


>>> def burst_seq(seq, indices): ... startpos = 0 ... for index in indices: ... yield seq[startpos:index] ... startpos = index ... yield seq[startpos:] ... >>> list(burst_seq(range(20), [5, 12, 17])) [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19]] >>> list(burst_seq(range(20), [])) [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]] >>> list(burst_seq(range(0), [5, 12, 17])) [[], [], [], []] >>>

Maxima mea culpa: usa una declaración for , y no está usando whizzbang cosas como itertools, zip (), None como centinela, lista de comprensiones, ...

;-)


indices = [5, 12, 17] input = range(20) output = [] reduce(lambda x, y: output.append(input[x:y]) or y, indices + [len(input)], 0) print output