Альтернативные способы разбиения числа на список цифр
После прочтения вот этого вопроса (Найти сумму и произведение цифр числа), у меня возник интерес к допустимым вариантам разбиения числа на список из цифр. Итак, есть число, которое мы разбиваем на список из отдельных цифр.
num = 123
Если мы делаем
y = list(map(int, str(num)))
То получаем массив чисел [1, 2, 3] Если же мы просто вызваем
y = list(str(num))
То получаем ['1', '2', '3'], что естественно идёт как массив символов. Так вот, существуют ли альтернативные функции преобразованию строки в массив чисел, но без map? Имею ввиду вшитые в пайтон или какую-нибудь библиотеку.
Сам я смог найти лишь такой вариант (вот в этом вопросе):
f = lambda n, digits=[]: f(n//10, [n%10] + digits) if n else digits or [0]
Но это явно не то, что я ищу. В общем я буду очень благодарен люому, кто мне подскажет альтернативы.
Ответы (5 шт):
import re
num = 124509333
digits = [int(x) for x in re.findall(r'\d', str(num))]
Ну раз речь о вариантах то еще один:
a = 4567
l = []
while a >= 1:
a, b = divmod(a, 10)
l.insert(0, b)
print(l)
1. Классический вариант без работы со строками чисто по остатку от деления:
def split(number):
result = []
while number > 0:
result.append(number % 10)
number //= 10
return result
2. А также моя однострочная реализация – ведь цикл while вполне можно заменить на for, т.к число итераций известно наперёд:
import math
split = lambda num: [num//10**i%10 for i in range(math.ceil(math.log10(num)))]
3. Ещё можно в функциональной парадигме определив opposite reduce:
def reduce_opposite(fun, num):
while num > 0:
it, num = fun(num)
yield it
split = lambda num: list(reduce_opposite(lambda x: (x%10, x//10), num))
Спасибо опыту LISP'a :D
Результат везде один:
>>> print(split(31415))
... [5, 1, 4, 1, 3]
При желании, все варианты можно можно дополнить reversed для более натурального порядка цифр в списке.
Есть одна интересная библиотека, которая работает много быстрее, чем лобовое str(int).
Правда на очень больших числах. Это библиотека gmpy2 - по сути обертка над сишной библиотекой быстрых вычислений GMP.
Если str(int) работает как O(n2), то их родная функция работает быстрее. Жаль исходного кода нет.
Итак:
text = 1000*"0123456789"
%timeit str(int(text))
3.28 ms ± 27.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit mpz(text).digits()
1.9 ms ± 13.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Ну это на случай, когда надо именно "стандартная функция из библиотеки".
Конечно, можно и так:
%timeit str(mpz(text))
1.91 ms ± 14.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)