views:

70

answers:

5

i am comparing updates to two strings. i did a:

 string1 != string2

and they turn out different. I put them in the "Add Watch" and i see the only difference is one has line breaks and the other doesnt'.:

 string1 = "This is a test. \nThis is a test";
 string2 = "This is a test. This is a test";

i basically want to do a compare but dont include line breaks. So if line break is the only difference then consider them equal.

A: 
string1.replace('\n','') != string2.replace('\n','')
Paul Creasey
A: 

Cant you just strip out the line breaks before comparing the strings?

E.g. (pseudocode)...

string1.replace('\n','') != string2.replace('\n','')
barrylloyd
@Paul Creasey: You beat me to it!
barrylloyd
+4  A: 

A quick and dirty way, when performance isn't much of an issue:

string1.Replace("\n", "") != string2.Replace("\n", "")
Dave Markle
+1  A: 

I'd suggest regex to reduce every space, tab, \r, \n to a single space :

Regex.Replace(string1, @"\s+", " ") != Regex.Replace(string2, @"\s+", " ")
Diadistis
But this will remove space and tab characters - I think the OP only wanted to ignore line breaks
barrylloyd
Yes, as I said it will, but I can't see why multiple spaces should matter when new lines are irrelevant
Diadistis
+1  A: 

Assuming:

  1. The sort of direct char-value-for-char-value comparison of != and == is what is wanted here, except for the matter of newlines.
  2. The strings are, or may, be large enough or compared often enough to make just replacing "\n" with an empty string too inefficient.

Then:

public bool LinelessEquals(string x, string y)
{
    //deal with quickly handlable cases quickly.
    if(ReferenceEquals(x, y))//same instance
        return true;         // - generally happens often in real code,
                             //and is a fast check, so always worth doing first.
    //We already know they aren't both null as
    //ReferenceEquals(null, null) returns true.
    if(x == null || y == null)
        return false;
    IEnumerator<char> eX = x.Where(c => c != '\n').GetEnumerator();
    IEnumerator<char> eY = y.Where(c => c != '\n').GetEnumerator();
    while(eX.MoveNext())
    {
        if(!eY.MoveNext()) //y is shorter
            return false;
        if(ex.Current != ey.Current)
            return false;
    }
    return !ey.MoveNext(); //check if y was longer.
}

This is defined as equality rather than inequality, so you could easily adapt it to be an implementation of IEqualityComparer<string>.Equals. Your question for a linebreak-less string1 != string2 becomes: !LinelessEquals(string1, string2)

Jon Hanna
let's see, +1 for taking the time to provide a good answer, +1 for the first part where you check for reference equality and null and -1 for linq overkill in a string comparison method. +1 overall :)
Diadistis
I put the lambda in there mainly because it made the code more compact, and it's a pretty straight-forward expression that would execute reasonably quickly. The old fashioned way would be to add a helper function that yield returned the characters that weren't newlines. The really old-fashioned (.NET 1.1) way would either have a helper class or be much more complicated in it's iteration.It's hard to have overkill in a string comparison method, in general string comparison can be very complicated indeed (consider the common case of ß matching SS in caseless compares).
Jon Hanna