1

How would I remove all whitespaces in a string but keep whitespaces in between "", here's a example.

I need

string idk = "Stackoverflow is a very \"helpful website to\" use";

To be

string idk = "Stackoverflowisavery\"helpful website to\"use";
Jan Köhler
  • 5,817
  • 5
  • 26
  • 35
  • Your example makes no sense. If you are using double-quotes (`"`) as string delimiters, properly escape the quotes within the string. Wither that, or use something else to delimit the string (for example (`This is "my string" example`] – Flydog57 Oct 16 '21 at 04:16
  • And the other question is can we see the attempted code so far? – Omar Abdel Bari Oct 16 '21 at 04:21
  • By the way, I don't know of anything that makes this easy, fir example, I don't think Regex will help. You need a simple state-machine parser (with two states, `within-quotes` and `not-within-quotes`). Loop through the string, character by character, behaving differently depending on the state – Flydog57 Oct 16 '21 at 04:21
  • There are around a dozen whitespace charcters in addition to the plain space. – TaW Oct 16 '21 at 08:57

3 Answers3

1

Got it!

        const string s = "This is a "quoted string"... or so I've been told...";
        StringBuilder sb = new StringBuilder();
        var quoteActive = false;

        foreach (char c in s)
        {
            if (c == '"')
            {
                quoteActive = !quoteActive;
            }
            if (c != ' ' || quoteActive)
            {
                sb.Append(c);
            }
        }
  • 1
    But you should also tak note of [How to correctly represent a whitespace character](https://stackoverflow.com/questions/11019561/how-to-correctly-represent-a-whitespace-character), because a `space` is something else than a `whitespace`... – Luuk Oct 16 '21 at 08:49
0

Upfront warning - I would recommend you consider carefully whether you would use this answer in a production system, because it's probably difficult for many to quickly grok how it works, as it uses features of C# that are seldom encountered. It's a great opportunity to talk about those features and give a reminder about their existence though

As an idle curio , here's a LINQ equivalent to what you have already

var b = false;
var t = s.Aggregate(new StringBuilder(), (sb, c) => ((b^=c=='"')||c!=' ') ? sb.Append(c) : sb);

It shortens the logic of the ifs to ((b^=c=='"')||c!=' '), to explain this it's probably worth picking it apart. Let's just look at the (b^=c=='"') part, aand see what it returns, for each char in the string:

    var s = " hello world \" this is \" a string";

    var b = false;
    foreach(char c in s){
      Console.WriteLine(c + " " + (b^=c=='"'));
    }

Prints:

  False
h False
e False
l False
l False
o False
  False
w False
o False
r False
l False
d False
  False
" True
  True
t True
h True
i True
s True
  True
i True
s True
  True
" False
  False
a False
  False
s False
t False
r False
i False
n False
g False

(b^=c=='"') expands to (b = b ^ c=='"') => "b is xor of itself and 'c is quote')

The use of XOR on the bool effectively causes the boolean B to toggle every time a quote is encountered. Because every assignment operation in C# returns a value, usually the result of the assignment, it means we can use the new value of b in a further test.

We are trying to work out "do we want to add the char or not?". In the above, the True are sorted - inside of a "..." we always want to add the char. Outside of a "..." we only want to add a char if it is NOT a space, hence adding ||c!=' '

    foreach(char c in s){
      Console.WriteLine(c + " " + ((b^=c=='"')||c!=' '))    ;
    }

Prints

  False
h True
e True
l True
l True
o True
  False
w True
o True
r True
l True
d True
  False
" True
  True
t True
h True
i True
s True
  True
i True
s True
  True
" True
  False
a True
  False
s True
t True
r True
i True
n True
g True

So now, everything that is "true" is "wanted", and everything that is "false" is "not wanted". This means a simple ternary will suffice for the aggregate: stringbuilder helpfully returns itself after an append, so if we do want to add a char, then sb.Append(char) adds the char and returns the stringbuilder

(sb, c) => ((b^=c=='"')||c!=' ') ? sb.Append(c) : sb

Is therefore a lambda that takes a stringbuilder and a char, and returns a stringbuilder, just like Aggregate demands


You could also use this form in a classic loop

foreach(char c in s)
  if((b^=c=='"')||c!=' '))
    sb.Append(c);

Would you actually use it in production code? Personally I think that massively depends on whether the next person after you will read it and go "oh yeah!" rather than "WTF". Tanveer has pointed out in the comments that any code that takes vastly more time to work out/explain than to write is potentially problematic in this regard, and it's a worthy point; if this style of code appeals to you and your colleagues then great. If not, go for something that's more "can understand it at a glance"

I personally wouldn't use code with a high WTF-factor, but it was a fun exercise/reminder of XOR and using assignment-returned values in the context of needing a single-statement expression

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
-2

You can use:

string idk = "Stackoverflow is a very \"helpful website to\" use";
idk = idk.Replace(" ", "");
Console.WriteLine(idk);
// prints message with removed whitespace