Chase Clark
Chase Clark

Reputation: 7

Replace every other instance of a string

I am attempting to replace every other instance of the word "happy" in a file using python. Here is the input and expected output.

Input: "hello happy car happy dog happy lane happy"
Output: "hello happy car sad dog happy lane sad"

I am attempting to adjust the following code but having problems. Any suggestions are greatly appreciated.

def nth_repl_all(s, sub, repl, nth):
    find = s.find(sub)
    # loop util we find no match
    i = 1
    while find != -1:
        # if i  is equal to nth we found nth matches so replace
        if i == nth:
            s = s[:find]+repl+s[find + len(sub):]
            i = 0
        # find + len(sub) + 1 means we start after the last match
        find = s.find(sub, find + len(sub) + 1)
        i += 1
    return s

Upvotes: 0

Views: 180

Answers (3)

enzo
enzo

Reputation: 11496

You can use some approaches:

  • Without using imports:
def replace(s):
    # Count how many 'happy's are there
    happy_count = s.count('happy')

    # Create a list of words where every other word is 'sad'
    words = ['sad' if i % 2 else 'happy' for i in range(happy_count)]
    
    # Replace all 'happy's with the words to replace
    return s.replace('happy', '{}').format(*words)
            
print(replace("hello happy car happy dog happy lane happy"))
# Output: hello happy car sad dog happy lane sad
  • Using itertools:
import itertools

def replace(s):
    # Count how many 'happy's are there
    happy_count = s.count('happy')

    # Create a infinite generator of 'happy's and 'sad's
    words = itertools.cycle(('happy', 'sad'))

    # Take only the 'happy_count' first elements
    words = itertools.islice(words, happy_count)

    return s.replace('happy', '{}').format(*words)
            
print(replace("hello happy car happy dog happy lane happy"))
# Output: hello happy car sad dog happy lane sad
  • Using itertools with list comprehensions:
import itertools

def replace(s):
    # Count how many 'happy's are there
    happy_count = s.count('happy')

    # Create a infinite generator of 'happy's and 'sad's
    words = itertools.cycle(('happy', 'sad'))

    # Get the next element of the generator 'happy_count' times
    words = [next(words) for _ in range(happy_count)]

    # Replace all 'happy's with the words to replace
    return s.replace('happy', '{}').format(*words)

print(replace("hello happy car happy dog happy lane happy"))
# Output: hello happy car sad dog happy lane sad

Upvotes: 2

cynthi8
cynthi8

Reputation: 861

The initialization of i = 1 outside the loop and the resetting of i = 0 should be the same value.

Assuming nth = 2 means replace every other/second instance of the word, the value should be reset to i = 1.

Currently, i = 0 means it will take two finds to increment i to 2 and another find to replace the substring instance, for an incorrect total of 3 finds.

Upvotes: 0

Barmar
Barmar

Reputation: 781068

Split your string into words, then loop over that making the replacements.

def nth_replace_all(s, sub, repl, nth):
    words = s.split()
    i = 1
    result = []
    for word in words:
        if word == sub:
            if i == nth:
                result.append(repl)
                i = 1
            else:
                result.append(word)
                i += 1
        else:
            result.append(word
    return " ".join(result)

Upvotes: 0

Related Questions