Right now, I have two char arrays, foo1[] and foo2[]. When I convert them to string and output to the console, they BOTH appear as bar. I know that I can do something like this:
int g;
for (int i=0;i<length.foo1;i++) { // loop from 0 to length of array
if (foo1[i]=foo2[i]) { // if foo1[0] and foo2[0] are the same char
g++; // increment a counter by 1
}
else // otherwise...
{
i=100; // set i to something that will halt the loop
}
if (g = length.foo1) { // if the incremented counter = length of array
return true; // arrays are equal, since g only increments
} // in the case of a match, g can ONLY equal the
else { // array length if ALL chars match
return false; // and if not true, false.
to compare them letter by letter, but I'm guessing there's an easier way. Interestingly, most of the googling I do for comparing char[] for eqivalency c# and similar keywords results in a whole mess of info about comparing STRING arrays, or comparing string or char arrays when PART of the array matches something or another...I've not been able to find anything about easy ways of testing char arrays as being equal. Is stepping through each array the best way? or is there some way to compare if foo1=foo2 or foo1==foo2? Neither of those worked for me.
Basically, I need to test if char foo1[] and char foo2[] are BOTH {B,A,R}
You are possibly looking for:
foo2.SequenceEqual(foo1)
I think you can use the SequenceEquals to compare the arrays, even though checking both lengths at first has better performance.
foo1.ToList().Intersect(foo2.ToList())
you can make a function of yours which will be faster then first converting char[] to string then compare two strings.
1. First compare length of the arrays if they are not equal return false.
2. start looping through and compare each char, If you find any diff return false else after the loop return true.
if(foo1.Length != foo2.Length){ return false;}
for(int i=0;i<foo1.Length;i++){
if(foo1[i] != foo2[i]){ return false;}
}
return true;
string s = new string(foo1);
string t = new string(foo2);
int c = string.Compare(s, t);
if(c==0){
//its equal
}
Related
I need to compare 2 strings using a For without using String.compare. (It's a homework ... I started programming C# 2 weeks ago)
I just can't figure out how to use the for loop to answer the question. I don't know what to put in for(). I tried for( string text1 = "something",) but I can't figure out what toput after the, in the for loop.
Since this is a homework question, I would recommend stop reading the answer as soon as you think you have enough information to solve it on your own before getting to the solution at the end.
Let's assume a simple method signature, first:
public static bool AreStringEqual(string str1, string str2)
{
}
And our goal is to implement (write the code for) this method. We'll assume our goal is Return true if the strings are equal, and return false if they are not. We won't do anything fancy like make it case insensitive.
We can do some basic checks on our strings, first. If they are of different length, then we can immediately assume the strings are different, and return false:
if (str1.Length != str2.Length)
{
return false;
}
This block checks the length, and if they differ, then false is immediately returned and the rest of the method doesn't get executed.
At this point we can guarantee the strings are the same length, so we can loop over the strings and compare them character by character using a for loop.
for(int counter = 0; counter < str1.Length; counter++)
{
}
This is a pretty standard for-loop that just counts a number from zero to one less than the length of the string. It doesn't matter if we use str1 or str2 for the upper bound of the loop since we already know they are the same length.
To get the character in a string, we can use the Indexer Syntax to get the character at a give position. The numbers start at zero in C# and .NET.
str1[0] gets the first character, str1[1] gets the second, etc.
We can then plug the variable in the for loop into the indexer for str1 and str2, then compare the characters. If they are not equal, then return false.
for(int counter = 0; counter < str1.Length; counter++)
{
if (str1[counter] != str2[counter])
{
return false;
}
}
And finally, if the code gets through the for loop without returning false, then return true at the end. Putting it all together, it looks like this:
public static bool AreStringEqual(string str1, string str2)
{
if (str1.Length != str2.Length)
{
return false;
}
for(int counter = 0; counter < str1.Length; counter++)
{
if (str1[counter] != str2[counter])
{
return false;
}
}
return true;
}
I am seeing lots of these in a method in our code:
int num1 = 0;
if (Char.IsDigit(myStr[2]) && Int32.TryParse(myStr[2].ToString(), out num1) == false)
{
valid = false;
}
So are they just making sure the third character us a digit?
The code shown parses the 3rd character only - checking if it is digit, then parsing the string representation of that single character. Instead, just use the numeric value of that character:
if(myStr[2] >= '0' && myStr[2] <= '9') {
num1 = (int)myStr[2] - (int)'0';
} else {
valid = false
}
You can safely skip the IsDigit() check as it's redundant.
TryParse() will fail if it's not a digit.
As it has been pointed out by others, Char.IsDigit() is quicker. If your code is performance sensitive the check makes sense.
If you leave the IsDigit check in place, then you can reduce TryParse to Int32.Parse() as at that point the parsing won't fail.
It looks like the code that you have is doing this for efficiency. Whoever coded this, knows the structure of the string in myStr to sometimes have a non-numeric symbol in the third position. That's why he made this optimization to check the third symbol before paying for the conversion of the character array to string which then gets parsed.
Chances are, this optimization is premature: although making a temporary throw-away string is not free, this optimization would make sense only in situations when you do it a lot in a very tight loop. In other words, you do it only if it shows up near the top in your performance profiler's output.
You can optimize this check to avoid if:
int num1 = 0;
valid &= !Char.IsDigit(myStr[2]) || Int32.TryParse(myStr[2].ToString(), out num1);
I don't believe you need the first part (it could also throw an IndexOutOfRangeException).
So I would probably use:
int num1 = 0;
if (myStr.Length > 2 && Int32.TryParse(myStr[2].ToString(), out num1) == false)
{
valid = false;
}
Char.IsDigit Method (String, Int32)
Indicates whether the character at the specified position in a specified string is categorized as a decimal digit.
Link
Int32.TryParse Method
Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the operation succeeded. This member is overloaded.
Link
Edit:
First I wrote that you can skip any of the check but now I am writing that you can not because
if (Char.IsDigit(myStr[2]) && Int32.TryParse(myStr[2].ToString(), out num1) == false)
{ }
Char.IsDigit() will return true if myStr[2] contains any of the Unicode characters listed here but Int.TryParse() will not convert any numbers except for 0-9 (not sure about this, as I have not checked all of them) so it will return false which is you are checking...
The condition you are checking can be understood by the following example:
string x = "AS௭s";
int s = 0;
if (Char.IsDigit(x[2]) && int.TryParse(x[2].ToString(), out s) == false)
{
// even if '௭` is Tamil Digit Seven and 'Char.IsDigit()' will return true but
// int.TryParse() will return false because it can not convert it
// so you are setting valid = false when the myStr contains a valid Unicode Character
// for a digit but It can not be converted to integer by TryParse method...
valid = false;
}
#Marc Gravell♦'s answer is the best solution for checking this condition...
Here's how I'd write it:
int num1 = 0;
try
{
num1 = Int32.Parse(myStr[2].ToString());
}
catch (Exception)
{
valid = false;
}
This does the same thing and is a lot easier to read imho, oh & you can log failed parses inside the catch.
Or you can do:
int num1 = 0;
valid = Int32.TryParse(myStr[2].ToString(), out num1);
In my string array, I want to look up some text and return the the line number of the first occurrence as an int.
This is working;
public static int LookUpLineNumber(String[] item, string TextToLookUp)
{
int m;
for (m = 0; m < item.Count(); m++)
{
if (item[m].Contains(TextToLookUp))
{
break;
}
}
return m++;
}
However, I am wondering if there is any way to optimize it for efficiency and length?
Speed comparison:
(average time on 10.000 runs with an string array of size 10.000)
Using my code:
1,259ms
Using Habib's code: Array.FindIndex<string>(item, r => r.Contains(TextToLookUp));
0,906ms
Your current solution looks OK. You can have return m; instead of return m++.
If you want to shorten your code you can use Array.FindIndex<T> like:
public static int LookUpLineNumber(String[] item, string TextToLookUp)
{
return Array.FindIndex<string>(item, r => r.Contains(TextToLookUp));
}
Not really sure if it would give you any performance gain.
If you need to do this multiple times, a suffix tree built out of the array would be the fastest approach:
http://en.wikipedia.org/wiki/Suffix_tree
However, if you are not re-using the array, then I think the approach you have is likely fastest, short of using a regex to do the contains, which may be faster if the regex is pre-compiled.
You can also do the following :-
Array.FindIndex(item,i=>i.Contains(TextToLookUp));
The above would work even if it is not sorted.
The above can be further optimized by using IndexOf operations instead of Contains and passing StringComparison.OrdinalIgnoreCase. Then you will have to compare it against 0.
I want to check if a string contains more than one character in the string?
If i have a string 12121.23.2 so i want to check if it contains more than one . in the string.
You can compare IndexOf to LastIndexOf to check if there is more than one specific character in a string without explicit counting:
var s = "12121.23.2";
var ch = '.';
if (s.IndexOf(ch) != s.LastIndexOf(ch)) {
...
}
You can easily count the number of occurences of a character with LINQ:
string foo = "12121.23.2";
foo.Count(c => c == '.');
If performance matters, write it yourself:
public static bool ContainsDuplicateCharacter(this string s, char c)
{
bool seenFirst = false;
for (int i = 0; i < s.Length; i++)
{
if (s[i] != c)
continue;
if (seenFirst)
return true;
seenFirst = true;
}
return false;
}
In this way, you only make one pass through the string's contents, and you bail out as early as possible. In the worst case you visit all characters only once. In #dasblinkenlight's answer, you would visit all characters twice, and in #mensi's answer, you have to count all instances, even though once you have two you can stop the calculation. Further, using the Count extension method involves using an Enumerable<char> which will run more slowly than directly accessing the characters at specific indices.
Then you may write:
string s = "12121.23.2";
Debug.Assert(s.ContainsDuplicateCharacter('.'));
Debug.Assert(s.ContainsDuplicateCharacter('1'));
Debug.Assert(s.ContainsDuplicateCharacter('2'));
Debug.Assert(!s.ContainsDuplicateCharacter('3'));
Debug.Assert(!s.ContainsDuplicateCharacter('Z'));
I also think it's nicer to have a function that explains exactly what you're trying to achieve. You could wrap any of the other answers in such a function too, however.
Boolean MoreThanOne(String str, Char c)
{
return str.Count(x => x==c) > 1;
}
Is there a better way to examine whether two string arrays have the same contents than this?
string[] first = new string[]{"cat","and","mouse"};
string[] second = new string[]{"cat","and","mouse"};
bool contentsEqual = true;
if(first.Length == second.Length){
foreach (string s in first)
{
contentsEqual &= second.Contains(s);
}
}
else{
contentsEqual = false;
}
Console.WriteLine(contentsEqual.ToString());// true
Enumerable.SequenceEquals if they're supposed to be in the same order.
You should consider using the intersect method. It will give you all the matching values and then you can just compare the count of the resulting array with one the arrays that were compared.
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.intersect.aspx
This is O(n^2). If the arrays have the same length, sort them, then compare elements in the same position. This is O(n log n).
Or you can use a hash set or dictionary: insert each word in the first array, then see if every word in the second array is in the set or dictionary. This is O(n) on average.
Nothing wrong with the logic of the method, but the fact that you're testing Contains for each item in the first sequence means the algorithm runs in O(n^2) time in general. You can also make one or two other smaller optimisations and improvements
I would implement such a function as follows. Define an extension method as such (example in .NET 4.0).
public static bool SequenceEquals<T>(this IEnumerable<T> seq1, IEnumerable<T> seq2)
{
foreach (var pair in Enumerable.Zip(seq1, seq2)
{
if (!pair.Item1.Equals(pair.Item2))
return;
}
return false;
}
You could try Enumerable.Intersect: http://msdn.microsoft.com/en-us/library/bb460136.aspx
The result of the operation is every element that is common to both arrays. If the length of the result is equal to the length of both arrays, then the two arrays contain the same items.
Enumerable.Union: http://msdn.microsoft.com/en-us/library/bb341731.aspx would work too; just check that the result of the Union operation has length of zero (meaning there are no elements that are unique to only one array);
Although I'm not exactly sure how the functions handle duplicates.