Reputation: 3689
Starting with any string, I need to ascertain whether that string comprises one or more instances of only a specified single character. For example "£££££" would pass my test, "wertf" would fail. The approach I have taken is as follows:
string source = "any string";
char[] candidate = source.ToCharArray();
char validCharacter = '£';
if (candidate.Length > 0)
{
// (code removed) if candidate length = 1 then just test candidate[0] against validCharacter
bool isValid = true;
int index = 0;
while (index < candidate.Length - 1)
{
if (candidate [index] != validCharacter )
{
isValid = false;
break;
}
index++;
}
if (isValid)
{
// success, do what needs doing
}
}
This works, as you would expect, but I can't help but feel that I might be missing a trick here. Is there a better, more concise, way of doing this that doesn't sacrifice the clarity of the above?
Upvotes: 0
Views: 216
Reputation: 9002
Use Distinct()
to remove duplicates and compare the character counts.
var pass = mystring.Count() > mystring.Distinct().Count();
EDIT
I misread and thought it was a duplicate of any character in the test string. The following is correct for "one or more instances of only a single character".
mystring.Distinct().Count() == 1
Upvotes: 2
Reputation: 41213
if(Regex.IsMatch(candidate, "^£+$")) {
// whatever it is you want to do
}
... or of course ...
if(Regex.IsMatch(candidate, "^" + Regex.Escape(validChar) + "+$") { ... }
Regex.Escape()
is there in case validChar
is a character with meaning in regular expressions, like *
, .
etc.
These are short, declarative (as long as the reader understands regular expressions), efficient, performance scales to long strings, and the idiom extends to more complicated patterns.
Upvotes: 0
Reputation: 223187
Use Enumerable.All<TSource> Method
bool result = (str.Length > 0 && str.All(r=> r == str[0]));
This would be efficient than using Distinct
and Count()
For your case it can be:
string source = "any string";
char validCharacter = '£';
bool result = source.Length > 0 && source.All(r=> r == validCharacter);
Upvotes: 3
Reputation: 75296
You just check with simpler code whether a string has the same character:
if (source.Distinct().Count() == 1)
{
// Pass
}
Edit:
If you need to check string comprises one or more instances of only a specified single character, you can use All
:
if (input.All(c => c == specificChar))
{
// Pass
}
Upvotes: 9
Reputation: 498904
Here is one way to do this:
if(source[0] != validCharacter) return false;
bool isValid = true;
for(int i = 1 ; i < source.Length; i++)
{
if(validCharacter != source[i])
{
isValid = false;
break;
}
}
Things to note: immediate fail if the first character doesn't match. string
already implements IEnumerable<char>
, so no need to use ToCharArray
with the extra allocations. The loop starts at index 1, always comparing to the first item and breaking as soon as it fails.
This is likely to be more efficient for long strings than Distinct
.
Upvotes: 2
Reputation: 6943
Your code is probably going to be the fastest, you could compact it somewhat by using a for
instead of a while
for (int i = 0; i < source.Length; i++) {
// existing equality check
}
Alternatively, here's another inefficient but more compact method (as it creates a new string in memory and checks against):
if (source == new String('£', source.Length)) {
// valid
}
Upvotes: 1
Reputation: 1568
you can try this:
string str = "test";
char b = '£';
bool isValid = false;
foreach (char a in str)
{
if (!a.Equals(b))
{
isValid = false;
}
}
Upvotes: 0
Reputation: 21475
In your algorithm you don't need the .ToCharArray()
. Just retrieve the character using source[index]
. This way you will only be reading the memory and reading every character just once.
Your code is the optimal solution. There are many tricks using LINQ but most will perform much worse. Any tricks with code like source.Trim(source[0])
will result into unnecessary creation of new strings and thus also in worse performance.
See the answer from Oded♦ that shortens your existing code.
Upvotes: 1
Reputation: 4399
string test1 = "Test";
string test2 = "TTTT";
test1.All(a => a == test1[0]);
test2.All(a => a == test2[0]);
Upvotes: 1