tags:

views:

416

answers:

3

is there a similar function in python that takes search(array) and replace(array) as a parameter? Then takes a value from each array and uses them to do search and replace on subject(string).

I know I can achieve this using for loops, but just looking more elegant way.

+3  A: 

I believe the answer is no.

I would specify your search/replace strings in a list, and the iterate over it:

edits = [(search0, replace0), (search1, replace1), (search2, replace2)] # etc.
for search, replace in edits:
    s = s.replace(search, replace)

Even if python did have a str_replace-style function, I think I would still separate out my search/replace strings as a list, so really this is only taking one extra line of code.

Finally, this is a programming language after all. If it doesn't supply the function you want, you can always define it yourself.

John Fouhy
yes, you are rigth. but builtin functions tend to be more efficient.
Mohamed
The problem with this solution is that edit #2 might replace something inserted by the edits before it, which I would expect to be absolutely to avoid.
kaizer.se
@kaizer.se: Yes, this is true. I don't know PHP but http://nz.php.net/str_replace says: "If search or replace are arrays, their elements are processed first to last." Only replacing non-overlapping search strings would be a difficult problem, I think.
John Fouhy
@Ainab: Sure, but remember what they say about premature optimization. I expect this simple code to be _fast enough_ for most situations. If you've profiled it and you need more speed, you could ask another question: "How can I speed this up?"
John Fouhy
A: 

Do it with regexps:

import re

def replace_from_list(replacements, str):
    def escape_string_to_regex(str):
        return re.sub(r"([\\.^$*+?{}[\]|\(\)])", r"\\\1", str)

    def get_replacement(match):
        return replacements[match.group(0)]

    replacements = dict(replacements)
    replace_from = [escape_string_to_regex(r) for r in replacements.keys()]
    regex = "|".join(["(%s)" % r for r in replace_from])
    repl = re.compile(regex)

    return repl.sub(get_replacement, str)

# Simple replacement:
assert replace_from_list([("in1", "out1")], "in1") == "out1"

# Replacements are never themselves replaced, even if later search strings match
# earlier destination strings:
assert replace_from_list([("1", "2"), ("2", "3")], "123") == "233"

# These are plain strings, not regexps:
assert replace_from_list([("...", "out")], "abc ...") == "abc out"

Using regexps for this makes the searching fast. This won't iteratively replace replacements with further replacements, which is usually what's wanted.

Glenn Maynard
A: 

Heh - you could use the one-liner below whose elegance is second only to its convenience :-P

(Acts like PHP when search is longer than replace, too, if I read that correctly in the PHP docs.):

** Edit: This new version works for all sized substrings to replace. **

>>> subject = "Coming up with these convoluted things can be very addictive."
>>> search = ['Coming', 'with', 'things', 'addictive.', ' up', ' these', 'convoluted ', ' very']
>>> replace = ['Making', 'Python', 'one-liners', 'fun!']
>>> reduce(lambda s, p: s.replace(p[0],p[1]),[subject]+zip(search, replace+['']*(len(search)-len(replace))))
'Making Python one-liners can be fun!'
Anon
Neat. Itertools can continue sequences better: `def cont(seq, elem=None): return itertools.chain(seq, itertools.repeat(elem))`; now use `cont(replace, '')`
kaizer.se