How to remove decimals from file (round them)? - c#

I have to open file, find all decimals, remove decimal part, round them and replace in the text. Result text should be print in the Console.
I tried to do it, but the only thing I made was to remove the decimal part. Please tell me how to round them and replace in the result text. Here is my code:
Console.WriteLine("Enter path to first file:");
String path1 = Console.ReadLine();
string text = File.ReadAllText(path1);
string pattern = #"(\d+)\.\d+";
if(File.Exists(path1) ){
foreach(string phrase in Regex.Split(text, pattern)){
Console.Write(phrase);
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}

You can use #"\d+([\.\,]\d+)" pattern to capture each number with any amount of decimals. Then use Regex.Replace with MatchEvaluator, where parse captured value as double then "cut" decimals by simple ToString("F0") (check about Fixed-point format).
Example below include decimals with comma , or . fraction separators with help of double.TryParse overload, where we can specify NumberStyles.Any and CultureInfo.InvariantCulture (from System.Globalization namespace) and simple replacement of comma , to dot .. Also works with negative numbers (e.g. -0.98765 in example):
var input = "I have 11.23$ and can spend 20,01 of it. "+
"Melons cost 01.25$ per -0.98765 kg, "+
"but my mom ordered me to buy 1234.56789 kg. "+
"Please do something with that decimals.";
var result = Regex.Replace(input, #"\d+([\.\,]\d+)", (match) =>
double.TryParse(match.Value.Replace(",", "."), NumberStyles.Any, CultureInfo.InvariantCulture, out double value)
? value.ToString("F0")
: match.Value);
// Result:
// I have 11$ and can spend 20 of it.
// Melons cost 1$ per -1 kg,
// but my mom ordered me to buy 1235 kg.
// Please do something with that decimals.
On "Aaaa 50.05 bbbb 82.52 cccc 6.8888" would work too with result of "Aaaa 50 bbbb 83 cccc 7".

You can use Math.Round on all matches that you can transform using Regex.Replace and a match evaluator as the replacement:
var text = "Aaaa 50.05 bbbb 82.52 cccc 6.8888";
var pattern = #"\d+\.\d+";
var result = Regex.Replace(text, pattern, x => $"{Math.Round(Double.Parse(x.Value))}");
Console.WriteLine(result); // => Aaaa 50 bbbb 83 cccc 7
See the C# demo.
The \d+\.\d+ regex is simple, it matches one or more digits, . and one or more digits. Double.Parse(x.Value) converts the found value to a Double, and then Math.Round rounds the number.

Related

How to separate numbers from words, chars and any other marks with whitespace in string

I'm trying to separate numbers from words or characters and any other punctuation with whitespace in string wrote them together e.g. string is:
string input = "ok, here is369 and777, and 20k0 10+1.any word.";
and desired output should be:
ok, here is 369 and 777 , and 20 k 0 10 + 1 .any word.
I'm not sure if I'm on right way, but now what I'm trying to do, is to find if string contains numbers and then somehow replace it all with same values but with whitespace between. If it is possible, how can I find all individual numbers (not each digit in number to be clearer), separated or not separated by words or whitespace and attach each found number to value, which can be used for all at once to replace it with same numbers but with spaces on sides. This way it returns only first occurrence of a number in string:
class Program
{
static void Main(string[] args)
{
string input = "here is 369 and 777 and 15 2080 and 579";
string resultString = Regex.Match(input, #"\d+").Value;
Console.WriteLine(resultString);
Console.ReadLine();
}
}
output:
369
but also I'm not sure if I can get all different found number for single replacement value for each. Would be good to find out in which direction to go
If what we need is basically to add spaces around numbers, try this:
string tmp = Regex.Replace(input, #"(?<a>[0-9])(?<b>[^0-9\s])", #"${a} ${b}");
string res = Regex.Replace(tmp, #"(?<a>[^0-9\s])(?<b>[0-9])", #"${a} ${b}");
Previous answer assumed that words, numbers and punctuation should be separated:
string input = "here is369 and777, and 20k0";
var matches = Regex.Matches(input, #"([A-Za-z]+|[0-9]+|\p{P})");
foreach (Match match in matches)
Console.WriteLine("{0}", match.Groups[1].Value);
To construct the required result string in a short way:
string res = string.Join(" ", matches.Cast<Match>().Select(m => m.Groups[1].Value));
You were on the right path. Regex.Match only returns one match and you would have to use .NextMatch() to get the next value that matches your regular expression. Regex.Matches returns every possible match into a MatchCollection that you can then parse with a loop as I did in my example:
string input = "here is 369 and 777 and 15 2080 and 579";
foreach (Match match in Regex.Matches(input, #"\d+"))
{
Console.WriteLine(match.Value);
}
Console.ReadLine();
This Outputs:
369
777
15
2080
579
This provides the desired output:
string input = "ok, here is369 and777, and 20k0 10+1.any word.";
var matches = Regex.Matches(input, #"([\D]+|[0-9]+)");
foreach (Match match in matches)
Console.Write("{0} ", match.Groups[0].Value);
[\D] will match anything non digit. Please note space after {0}.

Using regex to split string by Non Digit and Digit

Ive seen a few answers that are similar but none seem to go far enough. I need to split the string when the letters change to numbers and back. The trick is the pattern is variable meaning there can be any number of letter or number groupings.
For Example
AB1000 => AB 1000
ABC1500 => ABC 1500
DE160V1 => DE 160 V 1
FGG217H5IJ1 => FGG 217 H 5 IJ 1
Etc.
If you want to split the string, one way would be lookarounds:
string[] results = Regex.Split("FGG217H5IJ1", #"(?<=\d)(?=\D)|(?<=\D)(?=\d)");
Console.WriteLine(String.Join(" ", results)); //=> "FGG 217 H 5 IJ 1"
You can use a regex like this:
[A-Z]+|\d+
Working demo

Regex. Up to six digits after separator but not all zeros

I need input in this form:
first digit ist always 0
second is always . or ,
than up to six digits, but only digits not letters or other symbols
and not all zeros
private const string Pattern = #"^0(,|.)(?!0+$)+";
var regex = new Regex(Pattern, RegexOptions.IgnoreCase);
if (!regex.IsMatch(inputToCheck))
{...}
This works ok for all the conditions except one with digits only.
This input should be disabled too: "0,01a", "0.01a1", "0,01a0"
How can I extend my regex pattern to this condition?
Some examples of valid and invalid input.
Valid:
0,123456
0,01
0,010
0,2
invalid:
1,123456
2,123456
0,0
0,00
0,000
a
a,1
0,01a
0,01a1
0,01a0
I think you're on the right track. Here's my solution to this:
^0[,.](?!0+$)\d{1,6}$
This will make sure that the first digit is zero. It then checks that the next character is either a comma or a dot. Then, using a lookahead it ensures that the rest of the subject string is not entirely zeros. If this passes, it checks that the remaining characters are all digits.
You can use a regex like this:
^0[.,][1-9]{0,6}$
Of course this regex don't allow 0 after the , or .. If you want to allow 0 but restrict ending by 0 you can do:
^0[.,][0-9]{0,5}[1-9]$
And also you can shorten it a little to:
^0[.,]\d{0,5}[1-9]$
Try this expression
^^0(,|.)([0-9]{1,4}$)+
You shouldn't really be using regex to parse numbers, you can do it by just validating it as a number as so..
CultureInfo culture = new CultureInfo("de-DE");
string[] inputs = new string[]{"0,123456",
"0,01",
"1,123456",
"0,0"};
foreach(var input in inputs)
{
double val;
if(Double.TryParse(input, NumberStyles.Number, culture, out val)
&& Math.Round(val, 6) == val
&& val != 0.0
&& (int)val == 0)
Console.WriteLine("{0} is valid", input);
else
Console.WriteLine("{0} is invalid", input);
}
Output
0,123456 is valid
0,01 is valid
1,123456 is invalid
0,0 is invalid
IDEOne example

Replace using Regular Expression - fixed digit location

I would like to replace from a number of 16 digits, it's 5th to 10th digit.
How can that be achieved with a regular expression (C#)?
The way to do it is to capture in the inner and outer portions separately, like this:
// Split into 2 groups of 5 digits and 1 of 6
string regex = "(\\d{5})(\\d{5})(\\d{6})";
// Insert ABCDEF in the middle of
// match 1 and match 3
string replaceRegex = "${1}ABCDE${3}";
string testString = "1234567890999999";
string result = Regex.Replace(testString, regex, replaceRegex);
// result = '12345ABCDE999999'
Why use a regular expression? If by "number of 16 digits", you mean a 16 character long string representation of a number, then you'd probably be better off just using substring.
string input = "0000567890000000";
var output = input.Substring(0, 4) + "222222" + input.Substring(10, 6);
Or did you mean you want to swap the 5th and 10th digits? Your question isn't very clear.
Use the regular expression (?<=^\d{4})\d{6}(?=\d{6}$) to achieve it without capture groups.
It looks for 6 consecutive digits (5th to 10th inclusively) that are preceded by the first 4 digits and the last 6 digits of the string.
Regex.Replace("1234567890123456", #"(?<=^\d{4})\d{6}(?=\d{6}$)", "replacement");
Got it...
by creating 3 capturing groups:
([\d]{5})([\d]{5})([\d]{6})
keep capturing group1 and 3 and replace group2 with stars (or whatever)
$1*****$3
C# code below
string resultString = null;
try {
resultString = Regex.Replace(subjectString, #"([\d]{5})([\d]{5})([\d]{6})", "$1*****$2", RegexOptions.Singleline);
} catch (ArgumentException ex) {
// Syntax error in the regular expression
}

How to extract decimal number from string in C#

string sentence = "X10 cats, Y20 dogs, 40 fish and 1 programmer.";
string[] digits = Regex.Split (sentence, #"\D+");
For this code I get these values in the digits array
10,20,40,1
string sentence = "X10.4 cats, Y20.5 dogs, 40 fish and 1 programmer.";
string[] digits = Regex.Split (sentence, #"\D+");
For this code I get these values in the digits array
10,4,20,5,40,1
But I would like to get like
10.4,20.5,40,1
as decimal numbers. How can I achieve this?
Small improvement to #Michael's solution:
// NOTES: about the LINQ:
// .Where() == filters the IEnumerable (which the array is)
// (c=>...) is the lambda for dealing with each element of the array
// where c is an array element.
// .Trim() == trims all blank spaces at the start and end of the string
var doubleArray = Regex.Split(sentence, #"[^0-9\.]+")
.Where(c => c != "." && c.Trim() != "");
Returns:
10.4
20.5
40
1
The original solution was returning
[empty line here]
10.4
20.5
40
1
.
The decimal/float number extraction regex can be different depending on whether and what thousand separators are used, what symbol denotes a decimal separator, whether one wants to also match an exponent, whether or not to match a positive or negative sign, whether or not to match numbers that may have leading 0 omitted, whether or not extract a number that ends with a decimal separator.
A generic regex to match the most common decimal number types is provided in Matching Floating Point Numbers with a Regular Expression:
[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?
I only changed the capturing group to a non-capturing one (added ?: after (). It matches
If you need to make it even more generic, if the decimal separator can be either a dot or a comma, replace \. with a character class (or a bracket expression) [.,]:
[-+]?[0-9]*[.,]?[0-9]+(?:[eE][-+]?[0-9]+)?
^^^^
Note the expressions above match both integer and floats. To match only float/decimal numbers make sure the fractional pattern part is obligatory by removing the second ? after \. (demo):
[-+]?[0-9]*\.[0-9]+(?:[eE][-+]?[0-9]+)?
^
Now, 34 is not matched: is matched.
If you do not want to match float numbers without leading zeros (like .5) make the first digit matching pattern obligatory (by adding + quantifier, to match 1 or more occurrences of digits):
[-+]?[0-9]+\.[0-9]+(?:[eE][-+]?[0-9]+)?
^
See this demo. Now, it matches much fewer samples:
Now, what if you do not want to match <digits>.<digits> inside <digits>.<digits>.<digits>.<digits>? How to match them as whole words? Use lookarounds:
[-+]?(?<!\d\.)\b[0-9]+\.[0-9]+(?:[eE][-+]?[0-9]+)?\b(?!\.\d)
And a demo here:
Now, what about those floats that have thousand separators, like 12 123 456.23 or 34,345,767.678? You may add (?:[,\s][0-9]+)* after the first [0-9]+ to match zero or more sequences of a comma or whitespace followed with 1+ digits:
[-+]?(?<![0-9]\.)\b[0-9]+(?:[,\s][0-9]+)*\.[0-9]+(?:[eE][-+]?[0-9]+)?\b(?!\.[0-9])
See the regex demo:
Swap a comma with \. if you need to use a comma as a decimal separator and a period as as thousand separator.
Now, how to use these patterns in C#?
var results = Regex.Matches(input, #"<PATTERN_HERE>")
.Cast<Match>()
.Select(m => m.Value)
.ToList();
try
Regex.Split (sentence, #"[^0-9\.]+")
You'll need to allow for decimal places in your regular expression. Try the following:
\d+(\.\d+)?
This will match the numbers rather than everything other than the numbers, but it should be simple to iterate through the matches to build your array.
Something to keep in mind is whether you should also be looking for negative signs, commas, etc.
Check the syntax lexers for most programming languages for a regex for decimals.
Match that regex to the string, finding all matches.
If you have Linq:
stringArray.Select(s=>decimal.Parse(s));
A foreach would also work. You may need to check that each string is actually a number (.Parse does not throw en exception).
Credit for following goes to #code4life. All I added is a for loop for parsing the integers/decimals before returning.
public string[] ExtractNumbersFromString(string input)
{
input = input.Replace(",", string.Empty);
var numbers = Regex.Split(input, #"[^0-9\.]+").Where(c => !String.IsNullOrEmpty(c) && c != ".").ToArray();
for (int i = 0; i < numbers.Length; i++)
numbers[i] = decimal.Parse(numbers[i]).ToString();
return numbers;
}

Categories