4

I was just wondering if there is a more cpu efficient way of writing the following loop as I need to speed my program up?

for char in data:
    if char in self.key:
        match += chr(self.key.index(char))

Thanks in advance for any help.

1
  • What is self.key, a list? Commented Aug 31, 2013 at 16:36

3 Answers 3

7

Replace self.key with a dictionary; it is the membership testing against a list, as well as the .index() calls that are costing you the most performance; both require scans across the list.

Use str.join() to concatenate a series of characters; that builds one new string object instead of N new objects:

keys = {char: chr(i) for i, char in enumerate(self.key)}
match = ''.join([keys[char] for char in data if char in keys])

Dictionary membership tests and lookups are O(1) constant cost; by building the dictionary with char(..) values you can avoid multiple chr() calls per value; depending on how many values are re-used it could be faster to use char: i instead and move the chr() call to the list comprehension.

Sign up to request clarification or add additional context in comments.

3 Comments

Just a little confused: why wouldn't match = ''.join(keys[char] for char in data if char in keys) work? Forgive me if it is something stupid I'm missing.
@iCodez: See list comprehension without [ ], Python for the reason why; due to how str.join() operates a list comp is more efficient than a generator expression.
Thanks to everyone who responded. Lots of choices, went with Martijn's answer as it had the most votes. No offence to all those who provided other great alternatives as well. It really was a lot quicker than my attempt. Thanks again Clinton.
4

Yes, use a dictionary instead of a list. index operation is slow (it's O(log(N)) as is the check if the element is in the list, while dictionary access is O(1))

self.map = dict(zip(self.key, range(len(self.key)))
for char in data:
     if char in self.map:
        match += chr(self.map[char])

Also change the constant adding to the string to just one string concatenation using join and a generator expression inside (avoid list creation):

result = ''.join(chr(self.map[char]) for char in data if char in self.map)

2 Comments

Thanks to everyone who responded. Lots of choices, went with Martijn's answer as it had the most votes. No offence to all those who provided other great alternatives as well. It really was a lot quicker than my attempt. Thanks again Clinton.
@ViktorKerkez : Using a list comprehension is actually faster in the case of join(...).
3
match = ''.join(char for char in data if char in self.key)

1 Comment

Thanks to everyone who responded. Lots of choices, went with Martijn's answer as it had the most votes. No offence to all those who provided other great alternatives as well. It really was a lot quicker than my attempt. Thanks again Clinton.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.