1
\$\begingroup\$

I'm trying to replace a number of keywords with other corresponding values. I started with this method:

Dictionary<string, string> keywords = GetKeywords();
foreach (var pair in keywords)
{
    var re = new Regex($@"\b{pair.Key}\b");
    if (re.IsMatch(text))
        text = re.Replace(text, pair.Value);
}

..which becomes slower and slower when the number of keywords increases. So, I used a different method (by only scanning the string once and checking each word against the dictionary):

text =
    Regex.Replace(text, @"\w+", delegate (Match m)
    {
        string word = m.Value;
        string value;
        if (keywords.TryGetValue(word, out value))
            return value;
        else
            return word;
    });

..which worked great for the original requirement. However, I was forced to switch back to the first method because I need to match/replace keywords that are not 100% equal to what's in the dictionary. For example, in the first method, I would do something like this:

string keyword = pair.Key.Replace("e", "[eé]")
var re = new Regex($@"\b{keyword}\b");

Is there a way around this using the second method? Or any other methods faster than the first one?

Notes:

  • It's not just accented letters, so something like IgnoreNonSpace will not work.
  • Both regex patterns are a little bit more complicated, that is, they both have a negative lookahead ((?![^<]*>|[^&]*;)) but I don't think that affects the outcome as the pattern is essentially just matching single words.

The only solution I could think of is to "normalize" the keywords before adding them to the dictionary (e.g., replace "[eé]" with "e") and then "normalize" each word before passing it to TryGetValue() but I'd like to see if there's a better solution first because this one will be a little bit messy.

\$\endgroup\$

closed as off-topic by t3chb0t, Ludisposed, Sᴀᴍ Onᴇᴌᴀ, Graipher, 1201ProgramAlarm Dec 26 '18 at 3:24

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Lacks concrete context: Code Review requires concrete code from a project, with sufficient context for reviewers to understand how that code is used. Pseudocode, stub code, hypothetical code, obfuscated code, and generic best practices are outside the scope of this site." – t3chb0t, Ludisposed, Sᴀᴍ Onᴇᴌᴀ, Graipher, 1201ProgramAlarm
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 4
    \$\begingroup\$ Both regex patterns are a little bit more complicated but I don't think that's relevant. - on the contrary, they are very relevant because the whole question is about parsing and since there are no patterns, there is no parsing and your question becomes off-topic due to the lack of context. Please include everything. No body can give you any advice how to do it better if we don't see how it's currently done. \$\endgroup\$ – t3chb0t Dec 20 '18 at 11:09
  • \$\begingroup\$ @t3chb0t You can safely assume that the patterns in the question are the ones used and just ignore that sentence (which is what I did for my test case). Does that still make the question off-topic? Anyway, I added more context on what the removed bit of the patterns is. \$\endgroup\$ – Ahmed Abdelhameed Dec 20 '18 at 11:17
  • 1
    \$\begingroup\$ You are speaking about dictionaries and keywords etc but don't give us enough context as to how this looks like or what issue you exactly try to solve. I suggest reframing your question like that: I'm doing A, but this is slow, so I tried B, it was faster but I need to match/replace keywords that are not 100% equal to what's in the dictionary. (whatever this is - it needs explanation) - in this part you post the original and unchanged code... Then you can add another snippet that you've created for demonstration purposes - this one can be simplified if it properly reproduces the problem. \$\endgroup\$ – t3chb0t Dec 20 '18 at 12:23
  • \$\begingroup\$ Note also that this is not Stack Overflow. We do want to know the gritty details of your code and try to make it better, as opposed to answering one specific question, where one generally wants an abstracted, general piece of code (aka a Minimal, Complete and Verifiable Example). \$\endgroup\$ – Graipher Dec 23 '18 at 13:42
  • \$\begingroup\$ @Graipher I understand. Thank you for the feedback! \$\endgroup\$ – Ahmed Abdelhameed Dec 23 '18 at 16:04
0
\$\begingroup\$

I can be wrong, but it seems that the problem is that if you have a large number of keywords, you are defining a lot of regular expressions in vain. How about creating a single regex and replacing values only for found keywords?

var words = string.Join("|", keywords.Keys);
text = Regex.Replace(text, $@"\b({words})\b", delegate (Match m)
{
    return keywords[m.Value];
});
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.