'Why time taken to execute code changes with one line?

This is my first code:

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

This is my second code:

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

This is my third code:

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

I don't understand why replacing s with set(s) in 4th line takes less time to execute and replacing with set(s[:]) is even more better than the other two statements.

Can anyone help me to know why this happens?



Solution 1:[1]

After performing %timeit I found that @Barmar observation is correct. You should perform timeit on these function. set(s[:]) is expensive as compared to set(s)

For these 4 functions:

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)

I got following output:

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)

Also fastest method to check anagram will be XOR operator.

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

Performance: 667 ns ± 2.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1