0

I want to make the function which find for string in the array and then replace the corres[ponding element from the dictionary. so far i have tried this but i am not able to figure out few things like

  1. How can escape special characters
  2. I can i replace with match found. i tried \1 but it didn't work

dsds

def myfunc(h):
        myarray = {
                "#":"\\#",
                "$":"\\$",
                "%":"\\%",
                "&":"\\&",
                "~":"\\~{}",
                "_":"\\_",
                "^":"\\^{}",
                "\\":"\\textbackslash{}",
                "{":"\\{",
                "}":"\\}"                
                    }
        pattern = "[#\$\%\&\~\_\^\\\\\{\}]"
        pattern_obj = re.compile(pattern, re.MULTILINE)
        new = re.sub(pattern_obj,myarray[\1],h)

        return new

4 Answers 4

3

You're looking for re.sub callbacks:

def myfunc(h):
    rules = {
            "#":r"\#",
            "$":r"\$",
            "%":r"\%",
            "&":r"\&",
            "~":r"\~{}",
            "_":r"\_",
            "^":r"\^{}",
            "\\":r"\textbackslash{}",
            "{":r"\{",
            "}":r"\}"                
    }
    pattern = '[%s]' % re.escape(''.join(rules.keys()))
    new = re.sub(pattern, lambda m: rules[m.group()], h)
    return new

This way you avoid 1) loops, 2) replacing already processed content.

Sign up to request clarification or add additional context in comments.

3 Comments

i am not able to figure out what will be input parameter to lambda , and how will that gets passed
@user196264097: the parameter is a Match object (docs.python.org/dev/library/re.html#re.sub)
thanks man , i wonder you guys read every line of the documentation. i have usually gone through the docs but not line by line. I am usually stuck where i skip the lines :)
1

You can try to use re.sub inside a loop that iterates over myarray.items(). However, you'll have to do backslash first since otherwise that might replace things incorrectly. You also need to make sure that "{" and "}" happen first, so that you don't mix up the matching. Since dictionaries are unordered I suggest you use list of tuples instead:

def myfunc(h):
    myarray = [
            ("\\","\\textbackslash")
            ("{","\\{"),
            ("}","\\}"),
            ("#","\\#"),
            ("$","\\$"),
            ("%","\\%"),
            ("&","\\&"),
            ("~","\\~{}"),
            ("_","\\_"),
            ("^","\\^{}")]

    for (val, replacement) in myarray:
        h = re.sub(val, replacement, h)
    h = re.sub("\\textbackslash", "\\textbackslash{}", h)

    return h

3 Comments

I feel that h.replace(val, replacement) could be faster than re.sub(val, replacement, h) and will fit our question's case.
yes, I am not too familiar with the performance differences, but I think yours is more readable.
Thanks. Just was curious: yes, str.replace is faster than re.sub. 6.7x faster according to tests on my PC :)
1
  1. I'd suggest you to use raw literal syntax (r"") for better readability of the code.
  2. For the case of your array you may want just to use str.replace function instead of re.sub.
def myfunc(h):
    myarray = [
            ("\\", r"\textbackslash"),
            ("{", r"\{"),
            ("}", r"\}"),
            ("#", r"\#"),
            ("$", r"\$"),
            ("%", r"\%"),
            ("&", r"\&"),
            ("~", r"\~{}"),
            ("_", r"\_"),
            ("^", r"\^{}")]

    for (val, replacement) in myarray:
        h = h.replace(val, replacement)
    h = h.replace(r"\textbackslash", r"\textbackslash{}", h)

    return h

The code is a modification of @tigger's answer.

Comments

0

to escape metacharacters, use raw string and backslashes

r"regexp with a \* in it"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.