5
\$\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!

asked Nov 9, 2011 at 17:51
\$\endgroup\$
2
  • \$\begingroup\$ Here is a SO question where the answer recommends using a StringBuilder. \$\endgroup\$ Commented Nov 9, 2011 at 18:54
  • \$\begingroup\$ I once read an article by Jesse Liberty that said the decent support structure actually slowed the code down........ \$\endgroup\$ Commented Jul 23, 2012 at 15:41

3 Answers 3

5
\$\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]);
answered Nov 9, 2011 at 17:49
\$\endgroup\$
1
  • \$\begingroup\$ As elegant as it may seem, sadly this alternative is 3 times slower. \$\endgroup\$ Commented Mar 24, 2015 at 15:21
1
\$\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

answered Nov 9, 2011 at 18:10
\$\endgroup\$
1
\$\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 partial class SafeTag
{
 private static readonly IEnumerable<Replacement> _Replacements =
 [
 new Replacement("'", "`"),
 new Replacement("\"", "`"),
 new Replacement("&", "and"),
 new Replacement(",", ":"),
 new Replacement("\\", "/"),
 ];
 private static readonly Regex _Spaces = Spaces();
 public static string GetSafeTagName(this string tag)
 {
 StringBuilder parse = new(tag.ToUpper());
 parse = _Replacements.Aggregate(
 parse,
 (current, replacement) => current.Replace(replacement.Original, replacement.ToReplaceWith));
 return _Spaces.Replace(parse.ToString(), " ");
 }
 private readonly struct Replacement(string original, string toReplaceWith)
 {
 public string Original { get; } = original;
 public string ToReplaceWith { get; } = toReplaceWith;
 }
 [GeneratedRegex("\\s+", RegexOptions.Compiled)]
 private static partial Regex Spaces();
}
answered Nov 9, 2011 at 19:54
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.