Please see the answer of @KeyurPotdar for an explanation for why your original solution did not work.
For a list-comprehension-based solution to your issue (which it seems like you were after), you can create a mapping of inputs to outputs, and then iterate over the mapping with your inputs
mapping = {
'1': 'i',
'2': 'put',
'3': 'this',
'4': 'here',
}
sentence = ['1', '2', '3', '4']
newsentence = [mapping[word] for word in sentence]
# ['I', 'put', 'this', 'here']
This is nice, but if you decide to throw more inputs at mapping
for which you have not defined an output you would get a KeyError
. To easily handle this you can use dict.get
, which allows you to provide a fallback value to be returned if the given key is missing.
newsentence = [mapping.get(word, word) for word in sentence]
# ['I', 'put', 'this', 'here']
A good reference on dict.get
.
Not only is a mapping-based solution more efficient in this case (see @KeyurPotdar's notes on that), but separating your code into data and logic is The Right Thing To Do™.
If you can transform a problem from being code/logic based (such as the sequence of list comprehensions in the original question) to be mapping-based you will almost always win on maintainability and code clarity. Observe that this solution both data and logic are mixed:
newsentence = [n.replace('1', 'I') for n in sentence]
newsentence = [n.replace('2', 'put') for n in newsentence]
newsentence = [n.replace('3', 'this') for n in newsentence]
newsentence = [n.replace('4', 'here') for n in newsentence]
However, in a mapping based solution they are separated
# DATA
mapping = {
'1': 'i',
'2': 'put',
'3': 'this',
'4': 'here',
}
# LOGIC
newsentence = [mapping.get(word, word) for word in sentence]
What does this buy you? Suppose down the road you end up having to support mapping 1000 words, and these words change often. Having the words mixed with the logic makes them more challenging to find, and makes it harder to mentally decouple if a change will just affect the data or may also accidentally change control flow. With a mapping-based solution one is positive that a change only affects the data.
Consider that we needed to add a mapping of '1a'
to 'we'
. In the mixed logic/data example it would be very easy to miss changing sentence
to newsentence
:
newsentence = [n.replace('1', 'I') for n in sentence]
newsentence = [n.replace('1a', 'we') for n in sentence]
newsentence = [n.replace('2', 'put') for n in newsentence]
newsentence = [n.replace('3', 'this') for n in newsentence]
newsentence = [n.replace('4', 'here') for n in newsentence]
Oops! In the mapping-based example this type of error is not possible by design.
Further, by decoupling data from logic one can start storing the data in separate files (such as JSON or YAML). This makes version control a bit more straightforward. It then opens up the possibility to have user-customizable mappings that you do not have to hard-code into your script. Decoupling == good.
['1', '2', '3', '4']
/['i', 'put', 'this', 'here']
. Your desired output is['i', 'put', 'this', 'here']
. So there is no problem here?replace
is not the road you want to go down. Check out @KeyurPotdar's edit with adict
solution.