una tamaño metodos llenar listas lista for elementos comando arreglos agregar python list range integer

tamaño - Convertir una lista de enteros en rango en Python



metodos de listas en python (9)

Creo que las otras respuestas son difíciles de entender, y probablemente ineficientes. Espero que esto sea más fácil y más rápido.

def ranges(ints): ints = sorted(set(ints)) range_start = previous_number = ints[0] for number in ints[1:]: if number == previous_number + 1: previous_number = number else: yield range_start, previous_number range_start = previous_number = number yield range_start, previous_number

¿Existe algo en Python que pueda convertir una lista creciente de enteros en una lista de rango?

Por ejemplo, dado el conjunto {0, 1, 2, 3, 4, 7, 8, 9, 11} quiero obtener {{0,4}, {7,9}, {11,11}}.

Puedo escribir un programa para hacer esto, pero quiero saber si hay una función incorporada en Python


El uso de itertools.groupby() produce una implementación concisa pero difícil:

import itertools def ranges(i): for a, b in itertools.groupby(enumerate(i), lambda (x, y): y - x): b = list(b) yield b[0][1], b[-1][1] print list(ranges([0, 1, 2, 3, 4, 7, 8, 9, 11]))

Salida:

[(0, 4), (7, 9), (11, 11)]


En el caso de que Python no tenga esta característica, aquí hay una implementación

p = [] last = -2 start = -1 for item in list: if item != last+1: if start != -1: p.append([start, last]) start = item last = item p.append([start, last])


Esta es una mejora sobre la muy elegante respuesta de @juanchopanza . Este cubre la entrada no única y no ordenada y también es compatible con python3 :

import itertools def to_ranges(iterable): iterable = sorted(set(iterable)) for key, group in itertools.groupby(enumerate(iterable), lambda t: t[1] - t[0]): group = list(group) yield group[0][1], group[-1][1]

Ejemplo:

>>> x [44, 45, 2, 56, 23, 11, 3, 4, 7, 9, 1, 2, 2, 11, 12, 13, 45] >>> print( list(to_ranges(x))) [(1, 4), (7, 7), (9, 9), (11, 13), (23, 23), (44, 45), (56, 56)]


Este generador:

def ranges(p): q = sorted(p) i = 0 for j in xrange(1,len(q)): if q[j] > 1+q[j-1]: yield (q[i],q[j-1]) i = j yield (q[i], q[-1]) sample = [0, 1, 2, 3, 4, 7, 8, 9, 11] print list(ranges(sample)) print list(ranges(reversed(sample))) print list(ranges([1])) print list(ranges([2,3,4])) print list(ranges([0,2,3,4])) print list(ranges(5*[1]))

Produce estos resultados:

[(0, 4), (7, 9), (11, 11)] [(0, 4), (7, 9), (11, 11)] [(1, 1)] [(2, 4)] [(0, 0), (2, 4)] [(1, 1)]

Tenga en cuenta que las carreras de números repetidos se comprimen . No sé si eso es lo que quieres. Si no, cambie el > a a != .

Entiendo tu pregunta. Busqué en itertools e intenté pensar en una solución que se pudiera hacer en un par de líneas de Python, que se calificaría como "casi incorporada" , pero no se me ocurrió nada.


Generando pares de rango:

def ranges(lst): s = e = None r = [] for i in sorted(lst): if s is None: s = e = i elif i == e or i == e + 1: e = i else: r.append((s, e)) s = e = i if s is not None: r.append((s, e)) return r

Ejemplo:

>>> lst = [1, 5, 6, 7, 12, 15, 16, 17, 18, 30] >>> print repr(ranges(lst)) [(1, 1), (5, 7), (12, 12), (15, 18), (30, 30)]

Como generador:

def gen_ranges(lst): s = e = None for i in sorted(lst): if s is None: s = e = i elif i == e or i == e + 1: e = i else: yield (s, e) s = e = i if s is not None: yield (s, e)

Ejemplo:

>>> lst = [1, 5, 6, 7, 12, 15, 16, 17, 18, 30] >>> print repr('',''.join([''%d'' % s if s == e else ''%d-%d'' % (s, e) for (s, e) in gen_ranges(lst)])) ''1,5-7,12,15-18,30''


Nada incorporado, o en cualquier biblioteca que yo sepa. No es de mucha ayuda, lo sé, pero nunca he encontrado nada como lo que quieres.

Aquí hay algunas ideas para su programa al menos (en C ++, pero puede darle algunas otras ideas):

Convertir conjuntos de enteros en rangos.


Ponlo más corto:

ranges=lambda l:map(lambda x:(x[0][1],x[-1][1]),map(lambda (x,y):list(y),itertools.groupby(enumerate(l),lambda (x,y):x-y)))


Puede usar una lista de comprensión con una expresión generadora y una combinación de enumerate() e itertools.groupby() :

>>> import itertools >>> l = [0, 1, 2, 3, 4, 7, 8, 9, 11] >>> [[t[0][1], t[-1][1]] for t in ... (tuple(g[1]) for g in itertools.groupby(enumerate(l), lambda (i, x): i - x))] [[0, 4], [7, 9], [11, 11]]

Primero, enumerate() construirá tuplas a partir de los elementos de la lista y su índice respectivo:

>>> [t for t in enumerate(l)] [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 7), (6, 8), (7, 9), (8, 11)]

Luego groupby() esas tuplas usando la diferencia entre su índice y su valor (que será igual para valores consecutivos):

>>> [tuple(g[1]) for g in itertools.groupby(enumerate(l), lambda (i, x): i - x)] [((0, 0), (1, 1), (2, 2), (3, 3), (4, 4)), ((5, 7), (6, 8), (7, 9)), ((8, 11),)]

A partir de ahí, solo necesitamos crear listas a partir de los valores de la primera y la última tupla de cada grupo (que serán iguales si el grupo solo contiene un elemento).

También puede usar [(t[0][1], t[-1][1]) ...] para crear una lista de tuplas de rango en lugar de listas anidadas, o incluso ((t[0][1], t[-1][1]) ...) para convertir toda la expresión en un generator iterable que generará perezosamente las tuplas de rango sobre la marcha.