1

I've implemented the answer here to do token replacements of a string: https://stackoverflow.com/a/1231815/1224021

My issue now is when this method finds a token with a value that is not in the dictionary. I get the exception "The given key was not present in the dictionary." and just return the normal string. What I'd like to happen obviously is all the good tokens get replaced, but the offending one remains au naturale. Guessing I'll need to do a loop vs. the one line regex replace? Using vb.net. Here's what I'm currently doing:

Shared ReadOnly re As New Regex("\$(\w+)\$", RegexOptions.Compiled)
Public Shared Function GetTokenContent(ByVal val As String) As String
    Dim retval As String = val

    Try
        If Not String.IsNullOrEmpty(val) AndAlso val.Contains("$") Then

            Dim args = GetRatesDictionary()

            retval = re.Replace(val, Function(match) args(match.Groups(1).Value))

        End If

    Catch ex As Exception

        ' not sure how to handle?

    End Try

    Return retval

End Function
Community
  • 1
  • 1
James Barry
  • 229
  • 1
  • 2
  • 10

3 Answers3

1

The exception is likely thrown in the line

retval = re.Replace(val, Function(match) args(match.Groups(1).Value))

because this is the only place you are keying the dictionary. Make use of the Dictionary.ContainsKey method before accessing it.

retval = re.Replace(val, 
             Function(match)
                 return If(args.ContainsKey(match.Groups(1).Value), args(match.Groups(1).Value), val)
             End Function)
djv
  • 15,168
  • 7
  • 48
  • 72
  • I thought this worked but now see it messes up my html string. It repeats or replaces the wrong part when encountering a missing dictionary entry. Thanks for letting me know about ContainsKey though. – James Barry Aug 29 '14 at 16:26
1

This is what I got to work vs. the regex, which was also a suggestion on the original thread by Allen Wang: https://stackoverflow.com/a/7957728/1224021

Public Shared Function GetTokenContent(ByVal val As String) As String
    Dim retval As String = val

    Try
        If Not String.IsNullOrEmpty(val) AndAlso val.Contains("$") Then

            Dim args = GetRatesDictionary("$")

            retval = args.Aggregate(val, Function(current, value) current.Replace(value.Key, value.Value))

        End If

    Catch ex As Exception

    End Try

    Return retval

End Function
Community
  • 1
  • 1
James Barry
  • 229
  • 1
  • 2
  • 10
0

I know it's been a while since this question was answered, but FYI for anyone wanting to still use the Regex / Dictionary match approach, the following works (based on the sample in the OP question):

retVal = re.Replace(formatString,
                    match => args.ContainsKey(match.Groups[1].Captures[0].Value)
                        ? args[match.Groups[1].Captures[0].Value]
                        : string.Empty);

... or my full sample as a string extension method is:

 public static class StringExtensions
        {
// Will replace parameters enclosed in double curly braces
            private static readonly Lazy<Regex> ParameterReplaceRegex = new Lazy<Regex>(() => new Regex(@"\{\{(?<key>\w+)\}\}", RegexOptions.Compiled));

            public static string InsertParametersIntoFormatString(this string formatString, string parametersJsonArray)
            {
                if (parametersJsonArray != null)
                {
                    var deserialisedParamsDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(parametersJsonArray);

                    formatString = ParameterReplaceRegex.Value.Replace(formatString,
                        match => deserialisedParamsDictionary.ContainsKey(match.Groups[1].Captures[0].Value)
                            ? deserialisedParamsDictionary[match.Groups[1].Captures[0].Value]
                            : string.Empty);
                }

                return formatString;
            }
        }

There are a few things to note here: 1) My parameters are passed in as a JSON array, e.g.: {"ProjectCode":"12345","AnotherParam":"Hi there!"} 2) The actual template / format string to do the replacements on has the parameters enclosed in double curly braces: "This is the Project Code: {{ProjectCode}}, this is another param {{AnotherParam}}" 3) Regex is both Lazy initialized and Compiled to suit my particular use case of:

  • the screen this code serves may not be used often
  • but once it is, it will get heavy use
  • so it should be as efficient on subsequent calls as possible.
Ciaran
  • 543
  • 5
  • 14