Related
I am processing files in order to replace a list of pre-defined keywords with a pre- and a post-string (say "#" and ".") like this :
"Word Word2 anotherWord and some other stuff" should become "#Word. #Word2. #anotherWord. and some other stuff"
My keys are unique and processed the keys from longest key to smallest, so I know inclusion can only be on already
However, if I have key inclusion (e.g. Word2 contains Word), and if I do
"Word Word2 anotherWord and some other stuff"
.Replace("anotherWord", "#anotherWord.")
.Replace("Word2", "#Word2.")
.Replace("Word", "#Word.")
I get the following result:
"#Word. ##Word.2. #another#Word.. and some other stuff"
For sure, my approach isn't wokring. So what is the way to make sure I only replace a key in the string, if it is NOT contained in another key? I tried RegExp but didn't find the correct way. Or there is another solution?
Just use Regular expressions with word boundary if performance is not a key requirement:
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Subst
{
public class Program
{
public static void Main(string[] args)
{
var map = new Dictionary<string, string>{
{"Word", "#Word."},
{"anotherWord", "#anotherWord."},
{"Word2", "#Word2."}
};
var input = "Word Word2 anotherWord and some other stuff";
foreach(var mapping in map) {
input = Regex.Replace(input, String.Format("\\b{0}\\b", mapping.Key), Regex.Escape(mapping.Value));
}
Console.WriteLine(input);
}
}
}
One way is to use
string myString = String.Format("ORIGINAL TEXT {1} {2}", "TEXT TO PUT INSIDE CURLY BRACKET 1", "TEXT TO PUT IN CURLY BRACKET 2");
//Result: "ORIGINAL TEXT TEXT TO PUT INSIDE CURLY BRACKET 1 TEXT TO PUT IN CURLY BRACKET 2"
However, this requires your original text to have the curly brackets inside in the first place.
Quite messy, but you could always replace the words you are looking for with the Replace and then change the curly backets at the same time. There is probably a far better way of doing this but I cant think of it right now.
I suggest direct implementation, e.g.
private static String MyReplace(string value, params Tuple<string, string>[] substitutes) {
if (string.IsNullOrEmpty(value))
return value;
else if (null == substitutes || !substitutes.Any())
return value;
int start = 0;
StringBuilder sb = new StringBuilder();
while (true) {
int at = -1;
Tuple<string, string> best = null;
foreach (var pair in substitutes) {
int index = value.IndexOf(pair.Item1, start);
if (index >= 0)
if (best == null ||
index < at ||
index == at && best.Item1.Length < pair.Item1.Length) {
at = index;
best = pair;
}
}
if (best == null) {
sb.Append(value.Substring(start));
break;
}
sb.Append(value.Substring(start, at - start));
sb.Append(best.Item2);
start = best.Item1.Length + at;
}
return sb.ToString();
}
Test
string source = "Word Word2 anotherWord and some other stuff";
var result = MyReplace(source,
new Tuple<string, string>("anotherWord", "#anotherWord."),
new Tuple<string, string>("Word2", "#Word2."),
new Tuple<string, string>("Word", "#Word."));
Console.WriteLine(result);
Outcome:
#Word. #Word2. #anotherWord. and some other stuff
Regex alternative (order doesn't matter):
var result = Regex.Replace("Word Word2 anotherWord and some other stuff", #"\b\S+\b", m =>
m.Value == "anotherWord" ? "#anotherWord." :
m.Value == "Word2" ? "#Word2." :
m.Value == "Word" ? "#Word." : m.Value)
Or separate:
string s = "Word Word2 anotherWord and some other stuff";
s = Regex.Replace(s, #"\b" + Regex.Escape("anotherWord") + #"\b", "#anotherWord.");
s = Regex.Replace(s, #"\b" + Regex.Escape("Word2") + #"\b", "#Word2.");
s = Regex.Replace(s, #"\b" + Regex.Escape("Word") + #"\b", "#Word.");
Solved the problem using a two-loop-through approach as follows...
List<string> keys = new List<string>();
keys.Add("Word1"); // ... and so on
// IMPORTANT: algorithm works only when we are sure that one key cannot be
// included in another key with higher index. Also, uniqueness is
// guaranteed by construction, although the routine would work
// duplicate key...!
keys = keys.OrderByDescending(x => x.Length).ThenBy(x => x).ToList<string>();
// first loop: replace with some UNIQUE key hash in text
foreach(string key in keys) {
txt.Replace(key, string.Format("!#someUniqueKeyNotInKeysAndNotInTXT_{0}_#!", keys.IndexOf(key)));
}
// second loop: replace UNIQUE key hash with corresponding values...
foreach(string key in keys) {
txt.Replace(string.Format("!#someUniqueKeyNotInKeysAndNotInTXT_{0}_#!", keys.IndexOf(key)), string.Format("{0}{1}{2}", preStr, key, postStr));
}
You can split your string by ' ' and cycle through the string array. Compare each index of the array to your replacement strings and then concatenate them when finished.
string newString = "Word Word2 anotherWord and some other stuff";
string[] split = newString.Split(' ');
foreach (var s in split){
if(s == "Word"){
s = "#Word";
} else if(s == "Word2"){
s = "#Word2";
} else if(s == "anotherWord"){
s = "#anotherWord";
}
}
string finalString = string.Concat(split);
I was trying to remove spaces before sentence ending but had no success. I was thinking of doing it with Split function but it didn't go well. The only thing I succeeded at was adding spaces after sentence ending. Here is my code:
static void Main(string[] args)
{
System.Windows.Forms.OpenFileDialog dlgOpen = new System.Windows.Forms.OpenFileDialog();
if (dlgOpen.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
StreamReader sr = new StreamReader(dlgOpen.FileName);
string dat1 = sr.ReadToEnd();
string dat2 = Path.GetDirectoryName(dlgOpen.FileName);
string dat3 = Path.GetFileNameWithoutExtension(dlgOpen.FileName);
string dat4 = Path.GetExtension(dlgOpen.FileName);
dat2 = dat2 + "/" + dat3 + "_norm" + dat4;
sz1(ref dat1);
Console.Write(dat1);
StreamWriter sw = new StreamWriter(dat2, false);
sw.WriteLine(dat1);
sw.Flush();
sw.Close();
Console.ReadLine();
}
}
static void sz1(ref string dat1)
{
char[] ArrayCharacters = { '.', ':', ',', ';', '!', '?' };
int i = -1;
dat1 = dat1.Trim();
for (int k = 0; k < dat1.Length; k++)
{
dat1 = dat1.Replace(" ", " ");
}
do
{
i = dat1.IndexOfAny(ArrayCharacters, i + 1);
if (i != -1)
{
dat1 = dat1.Insert((i + 1), " ");
dat1 = dat1.Replace(" ", " ");
}
} while (i != -1);
do
{
i = dat1.IndexOfAny(ArrayCharacters, i + 1);
if (i != -1)
{
dat1 = dat1.Insert((i - 1), " ");
dat1 = dat1.Replace(" ", " ");
dat1 = dat1.Remove(i - 1, 1);
}
} while (i != -1);
}
One option is using regex:
string pattern = "\\s+$";
string replacement = "";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(dat1, replacement);
If you're just learning programming, then one solution that you should be familiar with is to use a loop to walk the string one character at a time, and since we're examining the end of the string, it makes sense to walk it backwards.
I'm assuming from your code (though it would be nice if you clarified it in your question) that you have a set of characters that are allowed at the end of a sentence, and you would like to leave these characters alone, but remove any additional spaces.
The logic, then, would be to start from the end of the string, and if a character is a valid ending character leave it alone. Otherwise, if it's a space, remove it. And finally, if it's neither then we're done.
Below is a method that uses this logic, along with a StringBuilder variable that is used to store the result. Starting at the end of the string, we capture the last characters, adding them to the result if they're valid and skipping them if they're spaces, until we reach a "regular" character, at which point we keep the rest of the string:
static string TrimEndSpaces(string input)
{
// If the input is null, there's nothing to do - just return null
if (input == null) return input;
// Our array of valid ending punctuation
char[] validEndingPunctuation = { '.', ':', ',', ';', '!', '?' };
// This will contain our final result
var result = new StringBuilder();
// Walk backwards through the input string
for (int i = input.Length - 1; i >= 0; i--)
{
if (validEndingPunctuation.Contains(input[i]))
{
// Valid character, so add it and keep going backwards
result.Insert(0, input[i]);
continue;
}
if (input[i] == ' ')
{
// Space character at end - skip it
continue;
}
// Regular character found - we're done. Add the rest of the string
result.Insert(0, input.Substring(0, i + 1));
break;
}
return result.ToString();
}
And here is an example usage, with some test sentences with varying endings of spaces, valid characters, null strings, empty strings, etc:
private static void Main()
{
var testInput = new List<string>
{
null,
"",
" ",
"Normal sentence test.",
"Test with spaces .",
"Test with multiple ending chars !?!?!",
"Test with only spaces at end ",
"Test with spaces after punctuation. ",
"Test with mixed punctuation and spaces ! ? ! ? ! "
};
foreach (var test in testInput)
{
// Format output so we can "see" null and empty strings
var original = test ?? "<null>";
if (original.Length == 0) original = "<empty>";
// Show original and the result. Wrap result in <> so we know where it ends.
Console.WriteLine($"{original.PadRight(50, '-')} = <{TrimEndSpaces(test)}>");
}
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
If you just want to remove them from the end, you can use:
if(myString.EndsWith(" ") == true)
{
myString = myString.TrimEnd();
}
Of course, you will need to consider the ending symbol ".", "!" or "?", you might want to exclude that char if the spaces are just before it.
Another approach would be:
var keepTrimming = true;
while(keepTrimming == true)
{
if(myString.EndsWith(" ") == true)
{
myString= myString.Remove(myString.Length - 1);
}
else
{
keepTrimming = false
}
}
i feel dumb for asking a most likely silly question.
I am helping someone getting the results he wishes for his custom compiler that reads all lines of an xml file in one string so it will look like below, and since he wants it to "Support" to call variables inside the array worst case scenario would look like below:
"Var1 = [5,4,3,2]; Var2 = [2,8,6,Var1;4];"
What i need is to find the first ";" after "[" and "]" and split it, so i stand with this:
"Var1 = [5,4,3,2];
It will also have to support multiple "[", "]" for example:
"Var2 = [5,Var1,[4],2];"
EDIT: There may also be Data in between the last "]" and ";"
For example:
"Var2 = [5,[4],2]Var1;
What can i do here? Im kind of stuck.
You can try regular expressions, e.g.
string source = "Var1 = [5,4,3,2]; Var2 = [2,8,6,Var1;4];";
// 1. final (or the only) chunk doesn't necessary contain '];':
// "abc" -> "abc"
// 2. chunk has at least one symbol except '];'
string pattern = ".+?(][a-zA-Z0-9]*;|$)";
var items = Regex
.Matches(source, pattern)
.OfType<Match>()
.Select(match => match.Value)
.ToArray();
Console.Write(string.Join(Environment.NewLine, items));
Outcome:
Var1 = [5,4,3,2]abc123;
Var2 = [2,8,6,Var1;4];
^([^;]+);
This regex should work for all.
You can use it like here:
string[] lines =
{
"Var1 = [5,4,3,2]; Var2 = [2,8,6,Var1;4];",
"Var2 = [5,[4],2]Var1; Var2 = [2,8,6,Var1;4];"
};
Regex pattern = new Regex(#"^([^;]+);");
foreach (string s in lines){
Match match = pattern.Match(s);
if (match.Success)
{
Console.WriteLine(match.Value);
}
}
The explanation is:
^ means starts with and is [^;] anything but a semicolon
+ means repeated one or more times and is ; followed by a semicolon
This will find Var1 = [5,4,3,2]; as well as Var1 = [5,4,3,2];
You can see the output HERE
public static string Extract(string str, char splitOn)
{
var split = false;
var count = 0;
var bracketCount = 0;
foreach (char c in str)
{
count++;
if (split && c == splitOn)
return str.SubString(0, count);
if (c == '[')
{
bracketCount++;
split = false;
}
else if (c == ']')
{
bracketCount--;
if (bracketCount == 0)
{
split = true;
}
else if (bracketCount < 0)
throw new FormatException(); //?
}
}
return str;
}
How can I split comma separated strings with quoted strings that can also contain commas?
Example input:
John, Doe, "Sid, Nency", Smith
Expected output:
John
Doe
Sid, Nency
Smith
Split by commas was ok, but I've got requirement that strings like "Sid, Nency" are allowed. I tried to use regexes to split such values. Regex ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)" is from Java question and it is not working good for my .NET code. It doubles some strings, finds extra results etc.
So what is the best way to split such strings?
It's because of the capture group. Just turn it into a non-capture group:
",(?=(?:[^""]*""[^""]*"")*[^""]*$)"
^^
The capture group is including the captured part in your results.
ideone demo
var regexObj = new Regex(#",(?=(?:[^""]*""[^""]*"")*[^""]*$)");
regexObj.Split(input).Select(s => s.Trim('\"', ' ')).ForEach(Console.WriteLine);
And just trim the results.
Just go through your string. As you go through your string keep track
if you're in a "block" or not. If you're - don't treat the comma as
a comma (as a separator). Otherwise do treat it as such. It's a simple
algorithm, I would write it myself. When you encounter first " you enter
a block. When you encounter next ", you end that block you were, and so on.
So you can do it with one pass through your string.
import java.util.ArrayList;
public class Test003 {
public static void main(String[] args) {
String s = " John, , , , \" Barry, John \" , , , , , Doe, \"Sid , Nency\", Smith ";
StringBuilder term = new StringBuilder();
boolean inQuote = false;
boolean inTerm = false;
ArrayList<String> terms = new ArrayList<String>();
for (int i=0; i<s.length(); i++){
char ch = s.charAt(i);
if (ch == ' '){
if (inQuote){
if (!inTerm) {
inTerm = true;
}
term.append(ch);
}
else {
if (inTerm){
terms.add(term.toString());
term.setLength(0);
inTerm = false;
}
}
}else if (ch== '"'){
term.append(ch); // comment this out if you don't need it
if (!inTerm){
inTerm = true;
}
inQuote = !inQuote;
}else if (ch == ','){
if (inQuote){
if (!inTerm){
inTerm = true;
}
term.append(ch);
}else{
if (inTerm){
terms.add(term.toString());
term.setLength(0);
inTerm = false;
}
}
}else{
if (!inTerm){
inTerm = true;
}
term.append(ch);
}
}
if (inTerm){
terms.add(term.toString());
}
for (String t : terms){
System.out.println("|" + t + "|");
}
}
}
I use the following code within my Csv Parser class to achieve this:
private string[] ParseLine(string line)
{
List<string> results = new List<string>();
bool inQuotes = false;
int index = 0;
StringBuilder currentValue = new StringBuilder(line.Length);
while (index < line.Length)
{
char c = line[index];
switch (c)
{
case '\"':
{
inQuotes = !inQuotes;
break;
}
default:
{
if (c == ',' && !inQuotes)
{
results.Add(currentValue.ToString());
currentValue.Clear();
}
else
currentValue.Append(c);
break;
}
}
++index;
}
results.Add(currentValue.ToString());
return results.ToArray();
} // eo ParseLine
If you find the regular expression too complex you can do it like this:
string initialString = "John, Doe, \"Sid, Nency\", Smith";
IEnumerable<string> splitted = initialString.Split('"');
splitted = splitted.SelectMany((str, index) => index % 2 == 0 ? str.Split(',') : new[] { str });
splitted = splitted.Where(str => !string.IsNullOrWhiteSpace(str)).Select(str => str.Trim());
How can I replace multiple spaces in a string with only one space in C#?
Example:
1 2 3 4 5
would be:
1 2 3 4 5
I like to use:
myString = Regex.Replace(myString, #"\s+", " ");
Since it will catch runs of any kind of whitespace (e.g. tabs, newlines, etc.) and replace them with a single space.
string sentence = "This is a sentence with multiple spaces";
RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);
sentence = regex.Replace(sentence, " ");
string xyz = "1 2 3 4 5";
xyz = string.Join( " ", xyz.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ));
I think Matt's answer is the best, but I don't believe it's quite right. If you want to replace newlines, you must use:
myString = Regex.Replace(myString, #"\s+", " ", RegexOptions.Multiline);
Another approach which uses LINQ:
var list = str.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
str = string.Join(" ", list);
It's much simpler than all that:
while(str.Contains(" ")) str = str.Replace(" ", " ");
Regex can be rather slow even with simple tasks. This creates an extension method that can be used off of any string.
public static class StringExtension
{
public static String ReduceWhitespace(this String value)
{
var newString = new StringBuilder();
bool previousIsWhitespace = false;
for (int i = 0; i < value.Length; i++)
{
if (Char.IsWhiteSpace(value[i]))
{
if (previousIsWhitespace)
{
continue;
}
previousIsWhitespace = true;
}
else
{
previousIsWhitespace = false;
}
newString.Append(value[i]);
}
return newString.ToString();
}
}
It would be used as such:
string testValue = "This contains too much whitespace."
testValue = testValue.ReduceWhitespace();
// testValue = "This contains too much whitespace."
myString = Regex.Replace(myString, " {2,}", " ");
For those, who don't like Regex, here is a method that uses the StringBuilder:
public static string FilterWhiteSpaces(string input)
{
if (input == null)
return string.Empty;
StringBuilder stringBuilder = new StringBuilder(input.Length);
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (i == 0 || c != ' ' || (c == ' ' && input[i - 1] != ' '))
stringBuilder.Append(c);
}
return stringBuilder.ToString();
}
In my tests, this method was 16 times faster on average with a very large set of small-to-medium sized strings, compared to a static compiled Regex. Compared to a non-compiled or non-static Regex, this should be even faster.
Keep in mind, that it does not remove leading or trailing spaces, only multiple occurrences of such.
This is a shorter version, which should only be used if you are only doing this once, as it creates a new instance of the Regex class every time it is called.
temp = new Regex(" {2,}").Replace(temp, " ");
If you are not too acquainted with regular expressions, here's a short explanation:
The {2,} makes the regex search for the character preceding it, and finds substrings between 2 and unlimited times.
The .Replace(temp, " ") replaces all matches in the string temp with a space.
If you want to use this multiple times, here is a better option, as it creates the regex IL at compile time:
Regex singleSpacify = new Regex(" {2,}", RegexOptions.Compiled);
temp = singleSpacify.Replace(temp, " ");
You can simply do this in one line solution!
string s = "welcome to london";
s.Replace(" ", "()").Replace(")(", "").Replace("()", " ");
You can choose other brackets (or even other characters) if you like.
no Regex, no Linq... removes leading and trailing spaces as well as reducing any embedded multiple space segments to one space
string myString = " 0 1 2 3 4 5 ";
myString = string.Join(" ", myString.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries));
result:"0 1 2 3 4 5"
// Mysample string
string str ="hi you are a demo";
//Split the words based on white sapce
var demo= str .Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
//Join the values back and add a single space in between
str = string.Join(" ", demo);
// output: string str ="hi you are a demo";
Consolodating other answers, per Joel, and hopefully improving slightly as I go:
You can do this with Regex.Replace():
string s = Regex.Replace (
" 1 2 4 5",
#"[ ]{2,}",
" "
);
Or with String.Split():
static class StringExtensions
{
public static string Join(this IList<string> value, string separator)
{
return string.Join(separator, value.ToArray());
}
}
//...
string s = " 1 2 4 5".Split (
" ".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries
).Join (" ");
I just wrote a new Join that I like, so I thought I'd re-answer, with it:
public static string Join<T>(this IEnumerable<T> source, string separator)
{
return string.Join(separator, source.Select(e => e.ToString()).ToArray());
}
One of the cool things about this is that it work with collections that aren't strings, by calling ToString() on the elements. Usage is still the same:
//...
string s = " 1 2 4 5".Split (
" ".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries
).Join (" ");
Many answers are providing the right output but for those looking for the best performances, I did improve Nolanar's answer (which was the best answer for performance) by about 10%.
public static string MergeSpaces(this string str)
{
if (str == null)
{
return null;
}
else
{
StringBuilder stringBuilder = new StringBuilder(str.Length);
int i = 0;
foreach (char c in str)
{
if (c != ' ' || i == 0 || str[i - 1] != ' ')
stringBuilder.Append(c);
i++;
}
return stringBuilder.ToString();
}
}
Use the regex pattern
[ ]+ #only space
var text = Regex.Replace(inputString, #"[ ]+", " ");
I know this is pretty old, but ran across this while trying to accomplish almost the same thing. Found this solution in RegEx Buddy. This pattern will replace all double spaces with single spaces and also trim leading and trailing spaces.
pattern: (?m:^ +| +$|( ){2,})
replacement: $1
Its a little difficult to read since we're dealing with empty space, so here it is again with the "spaces" replaced with a "_".
pattern: (?m:^_+|_+$|(_){2,}) <-- don't use this, just for illustration.
The "(?m:" construct enables the "multi-line" option. I generally like to include whatever options I can within the pattern itself so it is more self contained.
I can remove whitespaces with this
while word.contains(" ") //double space
word = word.Replace(" "," "); //replace double space by single space.
word = word.trim(); //to remove single whitespces from start & end.
Without using regular expressions:
while (myString.IndexOf(" ", StringComparison.CurrentCulture) != -1)
{
myString = myString.Replace(" ", " ");
}
OK to use on short strings, but will perform badly on long strings with lots of spaces.
try this method
private string removeNestedWhitespaces(char[] st)
{
StringBuilder sb = new StringBuilder();
int indx = 0, length = st.Length;
while (indx < length)
{
sb.Append(st[indx]);
indx++;
while (indx < length && st[indx] == ' ')
indx++;
if(sb.Length > 1 && sb[0] != ' ')
sb.Append(' ');
}
return sb.ToString();
}
use it like this:
string test = removeNestedWhitespaces("1 2 3 4 5".toCharArray());
Here is a slight modification on Nolonar original answer.
Checking if the character is not just a space, but any whitespace, use this:
It will replace any multiple whitespace character with a single space.
public static string FilterWhiteSpaces(string input)
{
if (input == null)
return string.Empty;
var stringBuilder = new StringBuilder(input.Length);
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (i == 0 || !char.IsWhiteSpace(c) || (char.IsWhiteSpace(c) &&
!char.IsWhiteSpace(strValue[i - 1])))
stringBuilder.Append(c);
}
return stringBuilder.ToString();
}
How about going rogue?
public static string MinimizeWhiteSpace(
this string _this)
{
if (_this != null)
{
var returned = new StringBuilder();
var inWhiteSpace = false;
var length = _this.Length;
for (int i = 0; i < length; i++)
{
var character = _this[i];
if (char.IsWhiteSpace(character))
{
if (!inWhiteSpace)
{
inWhiteSpace = true;
returned.Append(' ');
}
}
else
{
inWhiteSpace = false;
returned.Append(character);
}
}
return returned.ToString();
}
else
{
return null;
}
}
Mix of StringBuilder and Enumerable.Aggregate() as extension method for strings:
using System;
using System.Linq;
using System.Text;
public static class StringExtension
{
public static string CondenseSpaces(this string s)
{
return s.Aggregate(new StringBuilder(), (acc, c) =>
{
if (c != ' ' || acc.Length == 0 || acc[acc.Length - 1] != ' ')
acc.Append(c);
return acc;
}).ToString();
}
public static void Main()
{
const string input = " (five leading spaces) (five internal spaces) (five trailing spaces) ";
Console.WriteLine(" Input: \"{0}\"", input);
Console.WriteLine("Output: \"{0}\"", StringExtension.CondenseSpaces(input));
}
}
Executing this program produces the following output:
Input: " (five leading spaces) (five internal spaces) (five trailing spaces) "
Output: " (five leading spaces) (five internal spaces) (five trailing spaces) "
Old skool:
string oldText = " 1 2 3 4 5 ";
string newText = oldText
.Replace(" ", " " + (char)22 )
.Replace( (char)22 + " ", "" )
.Replace( (char)22 + "", "" );
Assert.That( newText, Is.EqualTo( " 1 2 3 4 5 " ) );
You can create a StringsExtensions file with a method like RemoveDoubleSpaces().
StringsExtensions.cs
public static string RemoveDoubleSpaces(this string value)
{
Regex regex = new Regex("[ ]{2,}", RegexOptions.None);
value = regex.Replace(value, " ");
// this removes space at the end of the value (like "demo ")
// and space at the start of the value (like " hi")
value = value.Trim(' ');
return value;
}
And then you can use it like this:
string stringInput =" hi here is a demo ";
string stringCleaned = stringInput.RemoveDoubleSpaces();
I looked over proposed solutions, could not find the one that would handle mix of white space characters acceptable for my case, for example:
Regex.Replace(input, #"\s+", " ") - it will eat your line breaks, if they are mixed with spaces, for example \n \n sequence will be replaced with
Regex.Replace(source, #"(\s)\s+", "$1") - it will depend on whitespace first character, meaning that it again might eat your line breaks
Regex.Replace(source, #"[ ]{2,}", " ") - it won't work correctly when there's mix of whitespace characters - for example "\t \t "
Probably not perfect, but quick solution for me was:
Regex.Replace(input, #"\s+",
(match) => match.Value.IndexOf('\n') > -1 ? "\n" : " ", RegexOptions.Multiline)
Idea is - line break wins over the spaces and tabs.
This won't handle windows line breaks correctly, but it would be easy to adjust to work with that too, don't know regex that well - may be it is possible to fit into single pattern.
The following code remove all the multiple spaces into a single space
public string RemoveMultipleSpacesToSingle(string str)
{
string text = str;
do
{
//text = text.Replace(" ", " ");
text = Regex.Replace(text, #"\s+", " ");
} while (text.Contains(" "));
return text;
}