Почему требуется время для выполнения изменений кода с одной строкой?

Это мой первый код:

def isAnagram(s,t):
    if len(s)!=len(t):
        return False
    for i in s:
        if s.count(i)!=t.count(i):
            return False
    return True

Это мой второй код:

def isAnagram(s,t):
    if len(s)!=len(t):
        return False
    for i in set(s):
        if s.count(i)!=t.count(i):
            return False
    return True

Это мой третий код:

def isAnagram(s,t):
    if len(s)!=len(t):
        return False
    for i in set(s[:]):
        if s.count(i)!=t.count(i):
            return False
    return True

Я не понимаю, почему замена s на set(s) в 4-й строке требует меньше времени для выполнения, а замена на set(s[:]) даже лучше, чем два других оператора.

Может ли кто-нибудь помочь мне узнать, почему это происходит?

Преобразование строки в набор удалит все дубликаты, поэтому вы будете повторять меньшее количество раз.

Barmar 24.12.2020 18:36

Я не могу придумать причину, почему set(s[:]) лучше, чем set(s). Это должно быть немного хуже, потому что он должен сделать копию списка, прежде чем преобразовать его в набор.

Barmar 24.12.2020 18:37

В зависимости от того, как именно тестируется код, более поздние запуски могут выполняться быстрее из-за подогрева кеша.

Samwise 24.12.2020 18:38

Кроме того, вы можете уменьшить свою функцию до return sorted(s) == sorted(t), чтобы проверить наличие анаграмм.

Joshua Nixon 24.12.2020 19:47

Важно показать, как вы тестировали. Если вы не использовали timeit для прогрева кэшей и отключения сборки мусора, то тест, вероятно, ненадежен. (хотя это ставит нас здесь в странное положение, потому что s[:] создает дополнительную работу по сборке мусора, поэтому в реальной ситуации это очень сильно снижает пропускную способность, даже если этот эффект задерживается)

Charles Duffy 08.05.2022 21:28
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После выполнения %timeit я обнаружил, что наблюдение @Barmar верно. Вы должны выполнить timeit для этих функций. set(s[:]) дороже по сравнению с set(s)

Для этих 4 функций:

def isAnagram(s,t):
    if len(s)!=len(t):
        return False
    a = set(s)
    for i in a:
        if s.count(i)!=t.count(i):
            return False
    return True

def isAnagram1(s,t):
    if len(s)!=len(t):
        return False
    a = set(s[:])
    for i in a:
        if s.count(i)!=t.count(i):
            return False
    return True

def isAnagram2(s,t):
    if len(s)!=len(t):
        return False
    for i in set(s):
        if s.count(i)!=t.count(i):
            return False
    return True

def isAnagram3(s,t):
    if len(s)!=len(t):
        return False
    for i in set(s[:]):
        if s.count(i)!=t.count(i):
            return False
    return True

a = "abcde"
b = "edabc"
%timeit isAnagram(a, b)
%timeit isAnagram1(a,b)
%timeit isAnagram2(a,b)
%timeit isAnagram3(a,b)

Я получил следующий вывод:

958 ns ± 5.37 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.01 µs ± 17.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
967 ns ± 9.61 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
987 ns ± 2.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Также самым быстрым методом проверки анаграммы будет оператор XOR.

def isAnagramXOR(s, t):
    res = 0
    for i,j in zip(s, t):
        res ^= ord(i) ^ ord(j)
    return not bool(res)

Производительность: 667 ns ± 2.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Другие вопросы по теме