-
-
Save carlsmith/b2e6ba538ca6f58689b4c18f46fef11c to your computer and use it in GitHub Desktop.
import re | |
def replace(string, substitutions): | |
substrings = sorted(substitutions, key=len, reverse=True) | |
regex = re.compile('|'.join(map(re.escape, substrings))) | |
return regex.sub(lambda match: substitutions[match.group(0)], string) |
@carlsmith
Firstly
Your code causes an error if there are non-string values in "substitutions". Numbers for example.
Secondly
In edited version, regex pattern (re.compile) is created once after object is created (and can be cached).
In your case - every time this function is called.
This can be quite an expensive operation. As far as I know, this was in an incorrect comparison of Rust and Go based on regular expressions example. In this "comparison" with permanent recompilation of regex pattern object in Rust code, Go managed to slightly overtake Rust.
In corrected testing (with an object created once), situation was reversed.
Your code causes an error if there are non-string values in "substitutions". Numbers for example.
Non-string values should be an error. I could just call str
to convert the args to strings, but it makes more sense to leave that to the user, if that's their intention. I don't want to coerce the wrong types, as that's not part of the function's purpose.
In edited version, regex pattern (re.compile) is created once after object is created (and can be cached).
It would be trivial to wrap my function in a function that takes a regex, and returns my function (now only accepting the substitutions, and enclosing the regex):
def f(regex):
def myfunc(subs): etc(regex, subs)
return myfunc
It's two extra lines. I'm just not seeing the need for even a simple class, or the purpose of the wacky method names??
You have your point of view, and I have my...
The principles of code readability are important to me.
I try to use lambda functions as little as possible, because they degrade performance and do not support typing.
In addition, I prefer to immediately make the functionality more flexible for adding new features in the future. It seems to me that it is more convenient to add a new methods or protocols than to rewrite everything.
I myself don't really like to use OOP unnecessarily, but I think the principle of encapsulation (in methods for example) is the most important.
PS: I only suggested my version, including your solution. With hope that this will help someone, according to OpenSource spirit.
I'm not attacking your programming principles =)
@dgr113 - Being totally honest, I haven't studied your code properly, and it uses some stuff I'm not familiar with, so can't offer much in the way of feedback, but it's always nice to have different solutions from different perspectives, in the same language.
Personally, I prefer minimalist solutions that tend to rely on the same, few dozen standard libraries, but that's mainly to do with being lazy, and wanting to support likeminded people.
If you could explain a bit about the advantages of your solution, I'd be interested, and expect other readers would find it useful too. As it stands, it's hard to see the advantage of rewriting a three-line function as a rather complex looking class (where no two method names use the same combination of (presumably meaningful) underscores). The code is well written, so you seem to know what you're doing. I just don't get what it improves really.