views:

75

answers:

3

Hi All,

I was just wondering if there is a simple way of doing this. i.e. Replacing the occurrence of consecutive characters with the same character.

For eg: - if my string is "something likeeeee tttthhiiissss" then my final output should be "something like this".

The string can contain special characters too including space.

Can you guys suggest some simple way for doing this.

+1  A: 

How about:

s = new string(s
     .Select((x, i) => new { x, i })
     .Where(x => x.i == s.Length - 1 || s[x.i + 1] != x.x)
     .Select(x => x.x)
     .ToArray());

In english, we are creating a new string based on a char[] array. We construct that char[] array by applying a few LINQ operators:

  1. Select: Capture the index i along with the current character x.
  2. Filter out charaters that are not the same as the subsequent character
  3. Select the character x.x back out of the anonymous type x.
  4. Convert back to a char[] array so we can pass to constructor of string.
Kirk Woll
@kirk - Sorry to ask, but can you explain this in a bit more detail? I did not understand.
Sachin Shanbhag
This is a LINQ query. I would not recommend using this to do what you are trying to do. It might work but looking at it you really have no idea what the intent of the code is.
Dismissile
@Dismissile, *you* might have no idea what the intent of the code is, but that's pretty subjective and I totally disagree.
Kirk Woll
It's not a subjective judgment to say that this is ugly and hard to read compared to the `foreach`, largely because of the author's poor naming choices (`x.x`? really?) If you wanted to write it functionally, it would be much clearer to implement a `PartitionBy` in C# which returns a sequence split according to a predicate, or to write a recursive version yourself (which is all of three lines.)
mquander
Most people would have no idea what the intent of this code is. It is subjective but it's a hell of a lot more complex than the regex sample and even the stringbuilder sample.
Dismissile
+2  A: 
string myString = "something likeeeee tttthhiiissss";

char prevChar = '';
StringBuilder sb = new StringBuilder();
foreach (char chr in myString)
{
    if (chr != prevChar) {
        sb.Append(chr);
        prevChar = chr;
    }
}
Gabriel McAdams
for should be foreach
MStodd
@MStodd: yes. Thanks for noticing that. My answer has been edited.
Gabriel McAdams
+3  A: 

This should do it:

var regex = new Regex("(.)\\1+");
var str = "something likeeeee!! tttthhiiissss";

Console.WriteLine(regex.Replace(str, "$1")); // something like! this

The regex will match any character (.) and \\1+ will match whatever was captured in the first group.

alexn
Does not work for special characters and whitespace.
MStodd
True, edited to reflect that.
alexn