[issue33647] Add re.replace(string, replacement_map)

2020-10-08 Thread Chris Jerdonek


Chris Jerdonek  added the comment:

Another API option is to use str.replace's existing arguments: str.replace(old, 
new[, count]). In addition to "old" and "new" being strings, they could also be 
lists of strings of equal length, similar to how str.maketrans() can accept two 
strings of equal length. Then, like maketrans(), each string in "old" would be 
replaced by the corresponding string at the same position in "new."

--
nosy: +chris.jerdonek

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33647] Add re.replace(string, replacement_map)

2018-05-26 Thread Paal Pedersen

Paal Pedersen  added the comment:

I forgot to put the ** in the input.

This is to further explain what I had in mind:

"""The meaning of this file is to show how the replace function can be
enhanced"""

# Today the replace api takes at most 3 arguments, old_string,
new_string, and optional numbers_of_replacements
# My wish is to update the replace to support a fourth optional
**kwargs argument

class Str(object):
def __init__(self, s=''):
self.original_str = s
self.new_str = s
# name replace2 is to not cause recursion of my function
def replace2(self, *args, **kwargs):
# Old api lives here ...
if len(args) == 2:
old_str, new_str = args
# do the old stuff
elif len(args) == 3:
old_str, new_str, numbers_of_replacements = args
#do the old stuff
# new api begins
if kwargs:
for k, v in kwargs.items():
# this one relies on the old api from string object
# str original function must differ
self.new_str = self.new_str.replace(k, v)
return self.new_str

def __str__(self):
return self.original_str

s = Str('my string is not cool')

replacement_dict = {'is': 'could',
'my': 'your',
'not': 'be',
'cool': 'awsome'}

print(s)
s2 = s.replace2(**replacement_dict)
print(s, s2, sep='\n')

If this is a really crappy though, I would like not to be made a fool out
of. I only want to improve, and I'm not crtizing the old api. I just want a
simplier life for everyone :)

Paal

lør. 26. mai 2018 kl. 02:21 skrev Raymond Hettinger :

>
> Raymond Hettinger  added the comment:
>
> > I would like an example added to the sub(pattern, function,
> > string) examples.
>
> That seems like the most reasonable way to go.
>
> --
> nosy: +rhettinger
>
> ___
> Python tracker 
> 
> ___
>

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33647] Add re.replace(string, replacement_map)

2018-05-26 Thread Serhiy Storchaka

Serhiy Storchaka  added the comment:

I'm -1 of adding support of this in str.replace. This is very non-trivial code, 
and unicodeobject.c is already one of largest and most complex files. Adding 
new complex code will make maintaining harder and can make the compiler 
producing less optimal code for other methods. str.replace is already good 
optimized, it is often better to call it several times than use other methods 
(regular expressions or str.translate).

You should be careful with sequential applying str.replace() if some keys are 
prefixes of other keys ({'a': 'x', 'ab': 'y'}). You should perform replacement 
in correct order. But this doesn't work either in cases like {'a': 'b', 'b': 
'a'}.

The regular expression based implementation should be more complex than Terry's 
example:

def re_replace(string, mapping):
def repl(m):
return mapping[m[0]]
pattern = '|'.join(map(re.escape, sorted(mapping, reverse=True)))
return re.sub(pattern, repl, string)

And it will be very inefficient, because creating and compiling a pattern is 
much slower than performing the replacement itself, and it can't be cached. 
This function would be not very useful for practical purposes. You will need to 
split it on two parts. First prepare a compiled pattern:

def repl(m):
return mapping[m[0]]
compiled_pattern = re.compile('|'.join(map(re.escape, sorted(mapping, 
reverse=True

And later use it:

newstring = compiled_pattern.sub(repl, string)

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33647] Add re.replace(string, replacement_map)

2018-05-25 Thread Raymond Hettinger

Raymond Hettinger  added the comment:

> I would like an example added to the sub(pattern, function, 
> string) examples.

That seems like the most reasonable way to go.

--
nosy: +rhettinger

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33647] Add re.replace(string, replacement_map)

2018-05-25 Thread Terry J. Reedy

Terry J. Reedy  added the comment:

Your proposal is underspecified.  (And 'yours' is inconsistent with 'your';-). 
If you want sequential replacememt in multiple scans, make sequential replace 
calls.  Use a loop if the number of replacement scans is variable or large.  To 
be sure of the order of replacements, a sequence is better than a dict, but 
dict.values() instead would work in the following code.

s = 'this is my string'
for old, new in (('my', 'your'), ('string', 'car')):
s = s.replace(old, new)
print(s)

If you want parallel replacement in a single scan, a different scanner is 
required.  If the keys (search strings) are all single letters, one should use 
str.translate.  For a general string to string mapping, use re.sub with a 
replacement function that does a lookup.

import re

s = 'this is my string'
subs = {'my': 'your', 'string': 'car'}
print(re.sub('|'.join(subs), lambda m: subs[m.group(0)], s))

In any case, the proposal to modify str.replace should be rejected.

However, the re code is not completely trivial (I did not work it out until 
now), so I think it plausible to add the following to the re module.

def replace(string, map):
"""Return a string with map keys replaced by their values.

*string* is scanned once for non-overlapping occurrences of keys.
"""
return sub('|'.join(map), lambda m: map[m.group(0)], string)

I would reference this in the str.translate entry for when keys are not 
restricted to letters.

If adding replace() is rejected, I would like an example added to the 
sub(pattern, function, string) examples.

--
nosy: +serhiy.storchaka, terry.reedy
stage:  -> test needed
title: Make string.replace accept a dict instead of two arguments -> Add 
re.replace(string, replacement_map)

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com