fynmnx
fynmnx

Reputation: 611

How to use list comprehensions to replace characters in a string?

Say I have a list of strings such '12hell0', I want to strip this down to say 'hello'. My idea was to do:

words = ['12hell0','123word', ...]
for word in words:
   stripped = ''.join([i for i in word if not i.isdigit()]

I know this will create 'hell', is there are a way to use check if it's '0' and then replace with 'o'? Not sure how to structure the comprehension with multiple conditions but using regular statements it would be like:

for word in words:
    stripped = ''
    word.replace('0','o')
    for char in word:
        if not char.isdigit():
           stripped+=char

Thank you for any help or guidance!

Upvotes: 1

Views: 4956

Answers (9)

Kushan Gunasekera
Kushan Gunasekera

Reputation: 8566

Try this,

>>> words =['12hell0','123word']
>>> [''.join(character for character in word.replace('0', 'o') if not character.isdigit()) for word in words]
['hello', 'word']

Upvotes: 0

dildeolupbiten
dildeolupbiten

Reputation: 1342

Here is the functional programming way:

f = lambda arg: list(
    map(
         lambda i: "".join(filter(
             lambda j: j.isalpha(), i.replace("0", "o"))
         ), arg
    )
)

words = ['12hell0','123word']
print(f(words))
# ['hello', 'word']

Upvotes: 0

zsheryl
zsheryl

Reputation: 93

You could use the regex library in python. The pattern '[^\d]+' searches for a group of consecutive non-digit characters.

  • ^: non
  • \d: digit
  • []: single character
  • +: one or more occurrence

Code:

import re
words = ['12hell0','123word']
new_words = [word.replace('0','o') for word in words]
stripped = [re.search('[^\d]+',word).group() if re.search('[^\d]+',word) else '' for word in new_words]

output: ['hello', 'word']

Upvotes: 1

Devesh Kumar Singh
Devesh Kumar Singh

Reputation: 20490

This is one way to do it via a list comprehension, although I would advice against it since it ends up being not too readable.

We iterate over the list of words, and for each word, we take character 'o' if we find a '0', a empty character '' if we find any other digit, and the character itself for all other cases, and join all of the via str.join

words = ['12hell0','123word']
words = [''.join('o' if c == '0' else '' if c.isdigit() else c for c in word) for word in words]
print(words)

The output will be

['hello', 'word']

Upvotes: 1

Alexander Santos
Alexander Santos

Reputation: 1691

You can do it like this:

words = ['12hell0','123word', ...]
new_words = [] # This will receive the changed words

for word in words: # Iterating through array elements
    # This will store the new word.
    new_word = ''.join([ch.replace('0', 'o') for ch in word if not ch.isdigit() or ch == '0'])
    new_words.append(new_word)
print(new_words)

NOTE: This can be not much pythonic. I would recommend using separated methods, instead of this way. Code must be legible, so this can make it harder to other developers to give maintenance.

List comprehension is awesome, but be careful.

Upvotes: 2

Eugene Sh.
Eugene Sh.

Reputation: 18341

You can do it in a one-liner if you really want to make the code to look not very comprehensible (pun intended):

"".join(['o' if i == '0' else i for i in "123hell0" if not i.isdigit() or i=='0'])

We can break it down: 'o' if i == '0' else i - will replace '0' with 'o'

The extra condition ...or i=='0' will make it to take zeros despite being digits.

Upvotes: 2

Sash Sinha
Sash Sinha

Reputation: 22370

You could just add an other if else to your list comprehension for the case where i == '0':

words =['12hell0','123word']
new_words = []
for word in words:
  stripped = ''.join([i if not i.isdigit() else 'o' if i == '0' else '' for i in word])
  new_words.append(stripped)
print(new_words)

Output:

['hello', 'word']

Upvotes: 1

CLpragmatics
CLpragmatics

Reputation: 645

You could write some transform() function that replaces all substrings with the strings you intend to produce for the surface structure, applying it to i only if your Boolean is True:

stripped = ''.join([transform(i) for i in word if not i.isdigit()]

nested conditions are impossible within a list comprehension, so use loops if you need that.

Upvotes: 1

Marcus Grass
Marcus Grass

Reputation: 1083

I think you're on the right track, using only list comprehension might become unreadable, in this case splitting the replace logic into a function might be the most legible solution. That way you can apply more logic or change your mind later without having to disturb so much of your code.

def replaceDigits(word):
    stripped = ""
    for char in word:
        if char == "0":
            stripped += "o"
        elif not char.isdigit():
            stripped += char
    return stripped


words = ['12hell0', '123word']
stripped = [replaceDigits(n) for n in words]
print(stripped)

Upvotes: 1

Related Questions