Speeding up the process of list-appending via if else statements

Question:

I have a list that contains strings that are a combination of "A", "B" and "C".

For example:

abc_list = ["AB", "AC", "AB", "BC", "BB", ...]

I now want to create a new list that translates every element again to "A", "B" and "C" with a simple rule.

The rule is as follows:

If the element is "AA", "AB" or "BA", then the new string element has to become "A".
If the element is "BB", "AC” or "CA”, then the new string element has to become "B".
If the element is "CC", "CB" or "BC", then the new string element has to become "C".

So the new list becomes:

new_abc_list = ["A", "B", "A", "C", "B", ...]

I’m doing it as follow for the moment, but I got a feeling it can be done much more efficient.

new_abc_list = []
for element in abc_list :
    if element == "AA":
        new_abc_list .append("A")
    elif element == "AB":
        new_abc_list .append("A")
    elif element == "BA":
        new_abc_list .append("A")
    elif element == "CB":
        new_abc_list .append("C")
    elif element == "CC":
        new_abc_list .append("C")
    elif element == "BC":
        new_abc_list .append("C")
    else:
        new_abc_list .append("B")
return new_abc_list 

What is a more efficient way of doing this?

Asked By: Steven01123581321

||

Answers:

This looks like a good job for a dictionary and a list comprehension:

mapper = {"AA": "A", "AB": "A", "BA": "A", "CB": "C", "CC": "C", "BC": "C"}

abc_list = ["AB", "AC", "AB", "BC", "BB"]

# find the value from key, default to 'B' if not found
new_abc_list = [mapper.get(x, 'B') for x in abc_list]

Output:

['A', 'B', 'A', 'C', 'B']

Complexity will be O(n) as dictionary search is O(1). In contrast your original code has to test all values until it find a match for each item in the loop.

timings

On 500k items (abc_list = ["AB", "AC", "AB", "BC", "BB"] * 100_000) with 6 tests:

# dictionary with list comprehension
27.8 ms ± 1.94 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# dictionary with for loop and append
56.4 ms ± 12.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# loop with tests
84.8 ms ± 11.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

worst case: 500k items that are not matching any test (abc_list = ['ZZ']*500_000):

# dictionary with list comprehension
35.1 ms ± 4.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# dictionary with for loop and append
48.2 ms ± 2.62 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# loop with tests
124 ms ± 20.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Answered By: mozway
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.