I have the following string "23456789"
and I need it to become "23 456 789".
I found this:
Regex.Replace(MYString, ".{3}", "$0 ");
but the number becomes "234 567 89".
It doesnt have to be Regex, everything is welcomed. Thank you
I have the following string "23456789"
and I need it to become "23 456 789".
I found this:
Regex.Replace(MYString, ".{3}", "$0 ");
but the number becomes "234 567 89".
It doesnt have to be Regex, everything is welcomed. Thank you
You could parse it to decimal
and use a custom NumberFormatInfo
with space as group-separator:
string input = "23456789";
decimal d = decimal.Parse(input);
var nfi = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone();
nfi.NumberGroupSeparator = " ";
nfi.NumberDecimalDigits = 0;
string formatted= d.ToString("N", nfi);
See: The Numeric ("N") Format Specifier
For what it's worth. Here is an approach which works not only for numeric strings but for all kind of strings and even for any kind of objects(if you remove the string.Join
):
string result = String.Join(" ", input.Reverse() // reverse input to get proper groups from right to left
.Select((c, index) => new { Char = c, Index = index })
.GroupBy(x => x.Index / 3, x=> x.Char) // group by index using integer division and then output the char
.Reverse() // again reverse to get original order
.Select(charGroup => new String(charGroup.Reverse().ToArray())));
Tim answer will works for decimal values but for really big numbers there is more generic solution. Note that it's performance killer because we are declaring new arrays and copy data few times:
string myString = "95555554643674373734737443737";
// revert source string
string reversedList = new string(myString.Reverse().ToArray());
// replace each trio
string replacedReversedList = Regex.Replace(reversedList, ".{3}", "$0 ");
// revert replaced string back to normal direction
string result = new string(replacedReversedList.Reverse().ToArray());
string oneLineResult = new string(Regex.Replace(new string(myString.Reverse().ToArray()), ".{3}", "$0 ").Reverse().ToArray());
Doesn't need to parse/format anything or multiple loops (like Reverse, ToArray, etc):
private static String CreateGroups(string source, int groupSize)
{
if (groupSize <= 0)
throw new ArgumentOutOfRangeException("groupSize", "must be greater zero.");
var sb = new StringBuilder();
var firstGroupLength = source.Length % groupSize;
var groupLength = firstGroupLength == 0 ? groupSize : firstGroupLength;
foreach (var item in source)
{
sb.Append(item);
groupLength--;
if (groupLength == 0)
{
groupLength = groupSize;
sb.Append(' ');
}
}
return sb.ToString(0, sb.Length-1);
}
use this code add namespace using System.Globalization;
var nfi = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone();
nfi.NumberGroupSeparator = " ";
string formatted = 23456789m.ToString("#,#", nfi);
I'd just do this for the general case:
string test = "23456789";
int n = 3; // Or whatever grouping you want.
for (int i = test.Length - n; i > 0; i -= n)
test = test.Insert(i, " ");
Console.WriteLine(test);
But if you are really trying to format a number rather than a string, I'd go with one of the other number-based answers in this thread.
This works:
var MyString = "23456789";
var result =
new string(
MyString
.Reverse()
.SelectMany((x, n) =>
new [] { x }.Concat(n % 3 == 2
? new [] { ' ' }
: Enumerable.Empty<char>()))
.Reverse()
.ToArray());
I get the required "23 456 789"
.
Here is my take on it.
This does not require cast to a numerical type and you can vary the size of a chunk
public static string Separate(this string source, int chunkSize = 3)
{
return string.Concat(source.Select((x, i) => (source.Length - i - 1) % chunkSize == 0 ? x + " " : x.ToString()));
}
Usage:
string str = "23456789";
var separatedBy3 = str.Separate(); //23 456 789
var separatedy4 = str.Separate(4); //2345 6789