I'm using C# and I want to check if a string contains one of ten characters, *, &, # etc etc. What is the best way?
views:
2189answers:
4The following would be the simplest method, in my view:
var match = str.IndexOfAny(new char[] { '*', '&', '#' }) != -1
Or in a possibly easier to read form:
var match = str.IndexOfAny("*&#".ToCharArray()) != -1
Depending on the context and performance required, you may or may not want to cache the char array.
As others have said, use IndexOfAny. However, I'd use it in this way:
private static readonly char[] Punctuation = "*&#...".ToCharArray();
public static bool ContainsPunctuation(string text)
{
return text.IndexOfAny(Punctuation) >= 0;
}
That way you don't end up creating a new array on each call. The string is also easier to scan than a series of character literals, IMO.
Of course if you're only going to use this once, so the wasted creation isn't a problem, you could either use:
private const string Punctuation = "*&#...";
public static bool ContainsPunctuation(string text)
{
return text.IndexOfAny(Punctuation.ToCharArray()) >= 0;
}
or
public static bool ContainsPunctuation(string text)
{
return text.IndexOfAny("*&#...".ToCharArray()) >= 0;
}
It really depends on which you find more readable, whether you want to use the punctuation characters elsewhere, and how often the method is going to be called.
EDIT: Here's an alternative to Reed Copsey's method for finding out if a string contains exactly one of the characters.
private static readonly HashSet<char> Punctuation = new HashSet<char>("*&#...");
public static bool ContainsOnePunctuationMark(string text)
{
bool seenOne = false;
foreach (char c in text)
{
// TODO: Experiment to see whether HashSet is really faster than
// Array.Contains. If all the punctuation is ASCII, there are other
// alternatives...
if (Punctuation.Contains(c))
{
if (seenOne)
{
return false; // This is the second punctuation character
}
seenOne = true;
}
}
return seenOne;
}
If you just want to see if it contains any character, I'd recommend using string.IndexOfAny, as suggested elsewhere.
If you want to verify that a string contains exactly one of the ten characters, and only one, then it gets a bit more complicated. I believe the fastest way would be to check against an Intersection, then check for duplicates.
private static char[] characters = new char [] { '*','&',... };
public static bool ContainsOneCharacter(string text)
{
var intersection = text.Intersect(characters).ToList();
if( intersection.Count != 1)
return false; // Make sure there is only one character in the text
// Get a count of all of the one found character
if (1 == text.Count(t => t == intersection[0]) )
return true;
return false;
}