4
\$\begingroup\$

Does anyone know of a better / cleaner way to write the following:

GetSafeTagName(txtUserInput.text);

public static string GetSafeTagName(string tag)
{
    tag = tag.ToUpper()
    .Replace("'","`")
    .Replace('"','`')
    .Replace("&", "and")
    .Replace(",",":")
    .Replace(@"\","/"); //Do not allow escaped characters from user
    tag = Regex.Replace(tag, @"\s+", " "); //multiple spaces with single spaces
    return tag;
}

Thanks!

\$\endgroup\$
  • \$\begingroup\$ wow, I didn't even know that site existed, I will ask over there thanks! \$\endgroup\$ – ToddBFisher Nov 9 '11 at 17:48
  • \$\begingroup\$ Here is a SO question where the answer recommends using a StringBuilder. \$\endgroup\$ – user786653 Nov 9 '11 at 18:54
  • \$\begingroup\$ I once read an article by Jesse Liberty that said the decent support structure actually slowed the code down........ \$\endgroup\$ – user15144 Jul 23 '12 at 15:41
4
\$\begingroup\$

You could use a regular expression and Dictionary<string, string> to do the search replace:

// This regex matches either one of the special characters, or a sequence of 
// more than one whitespace characters.
Regex regex = new Regex("['\"&,\\\\]|\\s{2,}");

var map = new Dictionary<string, string> {
    { "'", "`"},
    { "\"", "`"},
    { "&", "and" },
    { ",", ":" },
    { "\\", "/" }
};

// If the length of the match is greater that 1, then it's a sequence
// of spaces, and we can replace it by a single space. Otherwise, we
// use the dictionary to map the character.
string output = regex.Replace(input.ToUpper(), 
    m => m.Value.Length > 1 ? " " : map[m.Value]);
\$\endgroup\$
  • \$\begingroup\$ As elegant as it may seem, sadly this alternative is 3 times slower. \$\endgroup\$ – detay Mar 24 '15 at 15:21
0
\$\begingroup\$

When I had to do something similar, I used a Dictionary<string, string> to define the replacements.

And then something like this to replace:

foreach( KeyValuePair<string, string> pair in replacements)
{
    str = str.Replace(pair.Key, pair.Value);
}

http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx

\$\endgroup\$
0
\$\begingroup\$

I think your method is pretty readable and clean as it stands. However, if you want to simplify the method itself, I have a decent support structure that would do so and possibly speed it up for particularly long strings:

internal static class SafeTag
{
    private static readonly List<Replacement> replacements = new List<Replacement>
    {
        new Replacement("'", "`"),
        new Replacement("\"", "`"),
        new Replacement("&", "and"),
        new Replacement(",", ":"),
        new Replacement("\\", "/")
    };

    private static readonly Regex spaces = new Regex("\\s+", RegexOptions.Compiled);

    public static string GetSafeTagName(this string tag)
    {
        var parse = new StringBuilder(tag.ToUpper());
        replacements.ForEach(replacement => parse = parse.Replace(replacement.Original, replacement.ToReplaceWith));
        return spaces.Replace(parse.ToString(), " ");
    }

    private struct Replacement
    {
        private readonly string original;

        private readonly string toReplaceWith;

        internal Replacement(string original, string toReplaceWith)
        {
            this.original = original;
            this.toReplaceWith = toReplaceWith;
        }

        internal string Original
        {
            get
            {
                return this.original;
            }
        }

        internal string ToReplaceWith
        {
            get
            {
                return this.toReplaceWith;
            }
        }
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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