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!
3 Answers 3
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]);
-
\$\begingroup\$ As elegant as it may seem, sadly this alternative is 3 times slower. \$\endgroup\$detay– detay2015年03月24日 15:21:38 +00:00Commented Mar 24, 2015 at 15:21
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);
}
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();
}
StringBuilder
. \$\endgroup\$