tutorial lenguaje español descargar python

python - lenguaje - Convierte la lista de entradas a un número?



python wikipedia (15)

Tengo una lista de enteros que me gustaría convertir a un número como:

numList = [1, 2, 3] num = magic(numList) print num, type(num) >>> 123, <type ''int''>

¿Cuál es la mejor manera de implementar la función mágica ?

EDITAR
Encontré this , pero parece que tiene que haber una mejor manera.


Dos soluciones:

>>> nums = [1, 2, 3] >>> magic = lambda nums: int(''''.join(str(i) for i in nums)) # Generator exp. >>> magic(nums) 123 >>> magic = lambda nums: sum(digit * 10 ** (len(nums) - 1 - i) # Summation ... for i, digit in enumerate(nums)) >>> magic(nums) 123

En realidad, la solución orientada al map sale a la luz en mi caja; definitivamente no debería usar la sum para cosas que podrían ser números grandes:

import collections import random import timeit import matplotlib.pyplot as pyplot MICROSECONDS_PER_SECOND = 1E6 FUNS = [] def test_fun(fun): FUNS.append(fun) return fun @test_fun def with_map(nums): return int(''''.join(map(str, nums))) @test_fun def with_interpolation(nums): return int(''''.join(''%d'' % num for num in nums)) @test_fun def with_genexp(nums): return int(''''.join(str(num) for num in nums)) @test_fun def with_sum(nums): return sum(digit * 10 ** (len(nums) - 1 - i) for i, digit in enumerate(nums)) @test_fun def with_reduce(nums): return int(reduce(lambda x, y: x + str(y), nums, '''')) @test_fun def with_builtins(nums): return int(filter(str.isdigit, repr(nums))) @test_fun def with_accumulator(nums): tot = 0 for num in nums: tot *= 10 tot += num return tot def time_test(digit_count, test_count=10000): """ :return: Map from func name to (normalized) microseconds per pass. """ print ''Digit count:'', digit_count nums = [random.randrange(1, 10) for i in xrange(digit_count)] stmt = ''to_int(%r)'' % nums result_by_method = {} for fun in FUNS: setup = ''from %s import %s as to_int'' % (__name__, fun.func_name) t = timeit.Timer(stmt, setup) per_pass = t.timeit(number=test_count) / test_count per_pass *= MICROSECONDS_PER_SECOND print ''%20s: %.2f usec/pass'' % (fun.func_name, per_pass) result_by_method[fun.func_name] = per_pass return result_by_method if __name__ == ''__main__'': pass_times_by_method = collections.defaultdict(list) assert_results = [fun([1, 2, 3]) for fun in FUNS] assert all(result == 123 for result in assert_results) digit_counts = range(1, 100, 2) for digit_count in digit_counts: for method, result in time_test(digit_count).iteritems(): pass_times_by_method[method].append(result) for method, pass_times in pass_times_by_method.iteritems(): pyplot.plot(digit_counts, pass_times, label=method) pyplot.legend(loc=''upper left'') pyplot.xlabel(''Number of Digits'') pyplot.ylabel(''Microseconds'') pyplot.show()


Encontré algunos ejemplos que no son compatibles con Python 3. Probé uno de @Triptych

s = filter(str.isdigit, repr(numList)) num = int(s)

en python 3 va a dar error

TypeError: int() argument must be a string, a bytes-like object or a number, not ''filter''

creo que la manera más simple y compatible sería

def magic(num_list): return int("".join(map(str, num_list)))


Encontré este hilo al intentar convertir una lista al valor real de la int subyacente en términos de un puntero de estilo C, pero ninguna de las otras respuestas parece funcionar en este caso. Creo que la siguiente solución funciona según lo previsto y podría ser útil para otros aunque no responda necesariamente a la pregunta original.

def listToInt(x, reverseBytes=False): if reverseBytes: x = x[::-1] return reduce(lambda x,y: x*256+y, x)

listToInt([1, 249]) == 505

listToInt([249, 1], True) == 505

El valor principal de esto es emular el comportamiento de convertir una matriz de bytes a otro tipo de datos, por ejemplo, uint16, que Python parece no poder hacer de forma nativa, en un sistema endian grande o pequeño.


Este método funciona en 2.x siempre que cada elemento de la lista tenga solo un dígito. Pero en realidad no deberías usar esto. Es horrible.

>>> magic = lambda l:int(`l`[1::3]) >>> magic([3,1,3,3,7]) 31337


Esto parece bastante limpio, para mí.

def magic( aList, base=10 ): n= 0 for d in aList: n = base*n + d return n


Esto puede ser útil

def digits_to_number(digits): return reduce(lambda x,y : x+y, map(str,digits)) print digits_to_number([1,2,3,4,5])


Si está usando numpy (con import numpy as np ):

In [24]: x Out[24]: array([1, 2, 3, 4, 5]) In [25]: np.dot(x, 10**np.arange(len(x)-1, -1, -1)) Out[25]: 12345


Solo para completar, aquí hay una variante que usa print() (funciona en Python 2.6-3.x):

from __future__ import print_function try: from cStringIO import StringIO except ImportError: from io import StringIO def to_int(nums, _s = StringIO()): print(*nums, sep='''', end='''', file=_s) s = _s.getvalue() _s.truncate(0) return int(s)

Tiempo de rendimiento de diferentes soluciones

He medido el rendimiento de las funciones de @ cdleary . Los resultados son ligeramente diferentes.

Cada función probada con la lista de entrada generada por:

def randrange1_10(digit_count): # same as @cdleary return [random.randrange(1, 10) for i in xrange(digit_count)]

Puede suministrar su propia función a través del argumento de línea de comandos --sequence-creator=yourmodule.yourfunction (ver a continuación).

Las funciones más rápidas para un número dado de enteros en una lista ( len(nums) == digit_count ) son:

  • len(nums) en 1..30

    def _accumulator(nums): tot = 0 for num in nums: tot *= 10 tot += num return tot

  • len(nums) en 30..1000

    def _map(nums): return int(''''.join(map(str, nums))) def _imap(nums): return int(''''.join(imap(str, nums)))

|------------------------------+-------------------| | Fitting polynom | Function | |------------------------------+-------------------| | 1.00 log2(N) + 1.25e-015 | N | | 2.00 log2(N) + 5.31e-018 | N*N | | 1.19 log2(N) + 1.116 | N*log2(N) | | 1.37 log2(N) + 2.232 | N*log2(N)*log2(N) | |------------------------------+-------------------| | 1.21 log2(N) + 0.063 | _interpolation | | 1.24 log2(N) - 0.610 | _genexp | | 1.25 log2(N) - 0.968 | _imap | | 1.30 log2(N) - 1.917 | _map |

Para graficar la primera figura, descargue cdleary.py y make-figures.py y ejecute ( numpy y matplotlib deben estar instalados para trazar):

$ python cdleary.py

O

$ python make-figures.py --sort-function=cdleary._map / > --sort-function=cdleary._imap / > --sort-function=cdleary._interpolation / > --sort-function=cdleary._genexp --sort-function=cdleary._sum / > --sort-function=cdleary._reduce --sort-function=cdleary._builtins / > --sort-function=cdleary._accumulator / > --sequence-creator=cdleary.randrange1_10 --maxn=1000


Un trazador de líneas sin necesidad de lanzar hacia y desde str

def magic(num): return sum(e * 10**i for i, e in enumerate(num[::-1]))


Usando una expresión de generador:

def magic(numbers): digits = ''''.join(str(n) for n in numbers) return int(digits)


pseudo-código:

int magic(list nums) { int tot = 0 while (!nums.isEmpty()) { int digit = nums.takeFirst() tot *= 10 tot += digit } return tot }


si la lista contiene solo un número entero:

reduce(lambda x,y: x*10+y, list)


# Over-explaining a bit: def magic(numList): # [1,2,3] s = map(str, numList) # [''1'',''2'',''3''] s = ''''.join(s) # ''123'' s = int(s) # 123 return s # How I''d probably write it: def magic(numList): s = ''''.join(map(str, numList)) return int(s) # As a one-liner num = int(''''.join(map(str,numList))) # Functionally: s = reduce(lambda x,y: x+str(y), numList, '''') num = int(s) # Using some oft-forgotten built-ins: s = filter(str.isdigit, repr(numList)) num = int(s)


def magic(number): return int(''''.join(str(i) for i in number))


def magic(numbers): return int(''''.join([ "%d"%x for x in numbers]))