Получить самую значимую цифру в питоне

Скажи у меня есть список [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
Другие вопросы по тегам