Получить самую значимую цифру в питоне
Скажи у меня есть список [34523, 55, 65, 2]
Какой самый эффективный способ получить [3,5,6,2]
которые являются наиболее значительными цифрами. Если возможно, не меняя меняя каждый на str()
?
2 ответа
Предполагая, что вы имеете дело только с положительными числами, вы можете разделить каждое число на наибольшую степень на 10, меньшую, чем число, и затем взять результат.
>>> from math import log10, floor
>>> lst = [34523, 55, 65, 2]
>>> [floor(x / (10**floor(log10(x)))) for x in lst]
[3, 5, 6, 2]
Если вы используете Python 3, вместо получения результата вы можете использовать оператор целочисленного деления //
:
>>> [x // (10**floor(log10(x))) for x in lst]
[3, 5, 6, 2]
Однако я понятия не имею, является ли это более эффективным, чем просто преобразование в строку и разрезание первого символа. (Обратите внимание, что вам нужно быть немного более изощренным, если вам приходится иметь дело с числами от 0 до 1.)
>>> [int(str(x)[0]) for x in lst]
[3, 5, 6, 2]
Если это фрагмент кода, критичный к производительности, вы должны измерить два варианта и посмотреть, какой из них быстрее. Если он не входит в критичный для производительности кусок кода, используйте тот, который наиболее удобен для чтения.
Я сделал несколько таймингов, используя Python 3.6.1:
from timeit import timeit
from math import *
lst = list(range(1, 10_000_000))
# 3.6043569352230804 seconds
def most_significant_str(i):
return int(str(i)[0])
# 3.7258850016013865 seconds
def most_significant_while_floordiv(i):
while i >= 10:
i //= 10
return i
# 4.515933519736952 seconds
def most_significant_times_floordiv(i):
n = 10
while i > n:
n *= 10
return i // (n//10)
# 4.661690454738387 seconds
def most_significant_log10_floordiv(i):
return i // (10 ** (log10(i) // 1))
# 4.961193803243334 seconds
def most_significant_int_log(i):
return i // (10 ** int(log10(i)))
# 5.722346990002692 seconds
def most_significant_floor_log10(i):
return i // (10 ** floor(log10(i)))
for f in (
'most_significant_str',
'most_significant_while_floordiv',
'most_significant_times_floordiv',
'most_significant_log10_floordiv',
'most_significant_int_log',
'most_significant_floor_log10',
):
print(
f,
timeit(
f"""
for i in lst:
{f}(i)
""",
globals=globals(),
number=1,
),
)
Как видите, для чисел в range(1, 10_000_000)
, int(str(i)[0])
быстрее, чем другие методы. Самое близкое, что я мог получить, это использовать простой цикл while:
def most_significant_while_floordiv(i):
while i >= 10:
i //= 10
return i