How do I fetch last 3 digits of a string in c# - c#

How could I get the last three digits of this string?
var myString = "77441-Megrhfj654JHK";

You can try regular expressions to get last exactly 3 digits in a row:
using System.Text.RegularExpressions;
...
var myString = "77441-Megrhfj654JHK";
// Exactly 3 digits while start matching from the right
string digits = Regex.Match(myString, "[0-9]{3}", RegexOptions.RightToLeft).Value;
Console.WriteLine(digits);
Outcome:
654

Very straight forward LINQ example
public static class StringExtensions
{
public static string GetLastDigits( this string source, int count )
{
return new string( source
.Where(ch => Char.IsDigit(ch))
.Reverse()
.Take(count)
.Reverse()
.ToArray());
}
}
See working example on .net fiddle

In C# 8, you can use a range: myString[^3..];
Assuming that the input string is in a fixed format:
var lastThree = myString[^6..^3];
Or, in older C# versions:
var lastThree = myString.Substring(13, 3);
For just the last three numeric digits anywhere, something like:
var digits = new string(myString.Where(char.IsDigit).ToArray());
var lastThree = digits[^3..];

var myString = "77441-Megrhfj654JHK";
var digits = Regex.Match(myString, "[0-9]").Value;
return digits.Substring(Math.Max(digits.Length - 3,0));

Related

Trying to filter only digits in string array using LINQ

I'm trying to filter only digits in string array. This works if I have this array:
12324 asddd 123 123, but if I have chars and digits in one string e.g. asd1234, it does not take it.
Can u help me how to do it ?
int[] result = input
.Where(x => x.All(char.IsDigit))// tried with .Any(), .TakeWhile() and .SkipWhile()
.Select(int.Parse)
.Where(x => x % 2 == 0)
.ToArray();
Something like this should work. The function digitString will select only digits from the input string, and recombine into a new string. The rest is simple, just predicates selecting non-empty strings and even numbers.
var values = new[]
{
"helloworld",
"hello2",
"4",
"hello123world123"
};
bool isEven(int i) => i % 2 == 0;
bool notEmpty(string s) => s.Length > 0;
string digitString(string s) => new string(s.Where(char.IsDigit).ToArray());
var valuesFiltered = values
.Select(digitString)
.Where(notEmpty)
.Select(int.Parse)
.Where(isEven)
.ToArray();
You need to do it in 2 steps: First filter out all the invalid strings, then filter out all the non-digits in the valid strings.
A helper Method would be very readable here, but it is also possible with pure LINQ:
var input = new[]{ "123d", "12e", "pp", "33z3"};
input
.Where(x => x.Any(char.IsDigit))
.Select(str => string.Concat(str.Where(char.IsDigit)));
Possible null values should be drop to avoid NullReferenceException.
string.Join() suitable for concatenation with digit filtering.
Additinally empty texts should be dropped because it cannot be converted to an integer.
string[] input = new string[] { "1234", "asd124", "2345", "2346", null, "", "asdfas", "2" };
int[] result = input
.Where(s => s != null)
.Select(s => string.Join("", s.Where(char.IsDigit)))
.Where(s => s != string.Empty)
.Select(int.Parse)
.Where(x => x % 2 == 0)
.ToArray();
Using Linq Aggregate method and TryParse() can give you perfect result:
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
var input = new string[] { "aaa123aaa124", "aa", "778", "a777", null };
var result = input.Aggregate(
new List<int>(),
(x, y) =>
{
if (y is null)
return x;
var digitOnlyString = Regex.Replace(y, "[^0-9]", string.Empty);
if (int.TryParse(digitOnlyString, out var temp) && temp % 2 == 0)
x.Add(temp);
return x;
})
.ToArray();
Max,
You can do this in a single expression like so:
using System.Linq;
using System.Text.RegularExpressions;
var input = new[] { "aaa123aaa124", "aa", "778", "a777", null };
var rx = new Regex(#"[0-9]+");
var numbersOnly = input.Where(s => !string.IsNullOrEmpty(s) && rx.IsMatch(s))
.Select(s => string.Join("", rx.Matches(s).Cast<Match>().Select(m => m.Value)));
foreach (var number in numbersOnly) Console.WriteLine(number);
Which returns:
123124
778
777
if I have chars and digits in one string e.g. asd1234, it does not take it
Apparently you want to parse this line also. You want to translate "asd1234" to "1234" and then parse it.
But what if your input sequence of strings contains a string with two numbers: "123asd456". Do you want to interpret this as "123", or maybe as "123456", or maybe you consider this as two numbers "123" and "456".
Let's assume you don't have this problem: every string contains at utmost one number, or if you have a string with more than one number, you only want the first number.
In fact, you only want to keep those string that are "zero or more non-digits followed by one or more digits followed by zero or more characters.
Enter Regular Expressions!
const string regexTxt = "\D*\d+.*";
Regex regex = new Regex(regexTxt);
\D: any non-digit
*: zero or more
\d: any digit
+: one or more
. any character
(...) capture the parts between the parentheses
So this regular expression matches any string that starts with zero or more non-digits, followed by at least one digit, followed by zero or more characters. Capture the "at least one digit" part.
If you try to Match() an input string with this regular expression, you get a Match object. Property Success tells you whether the input string is according to the regular expression.
The Match object has a property Groups which contains all Matches. Groups[0] is the complete string, Groups1 contains a Group which has the first captured string in property Value.
A simple program that shows how to use the regular expression:
const string regexTxt = #"\D*(\d+).*";
Regex regex = new Regex(regexTxt);
var lines = new string[]
{
String.Empty,
"A",
"A lot of text, no numbers",
"1",
"123456",
"Some text and then a number 123",
"Several characters, then a number: 123 followed by another number 456!",
"___123---456...",
};
foreach (var line in lines)
{
Match match = regex.Match(line);
if (match.Success)
{
string capturedDigits = match.Groups[1].Value;
int capturedNumber = Int32.Parse(capturedDigits);
Console.WriteLine("{0} => {1}", line, capturedNumber);
}
}
Or in a LINQ statement:
const string regexTxt = #"\D*(\d+).*";
Regex regex = new Regex(regexTxt);
IEnumerable<string> sourceLines = ...
var numbers= sourceLines
.Select(line => regex.Match(line)) // Match the Regex
.Where(match => match.IsMatch) // Keep only the Matches that match
.Select(match => Int32.Parse(match.Groups[1].Value);
// Finally Parse the captured text to int

Regex extract from string xx:xx:xx format

I am very new to programming and I have a question, I am trying to use Regex method to extract hours, minutes and seconds from a string and putting them into an array, but so far I can do it with only one number:
int initialDay D = 0;
string startDay = Console.ReadLine(); //input: "It started 5 days ago"
var resultString = Regex.Match(startDay, #"\d+").Value;
initialDay = Int32.Parse(resultString); // initialDay here equals 5.
How do manage to read from a string 06: 11: 33, and transform these hours, minutes and seconds into an array of ints? So the resulting array would be like this:
int[] array = new int[] {n1, n2, n3}; // the n1 would be 6, n2 would be 11 and n3 would be 33
Thank you for your time in advance!
If the input is in this format (dd:dd:dd), you actually don't need regex in this. You can use String.Split() method. For example:
string test = "23:22:21";
string []res = test.Split(':');
The res array will now contains "23", "22", "21" as its elements. You just then need to convert them into int.
Unless you are trying to learn regular expressions, there is no reason for you to perform this parsing yourself.
Use TimeSpan.Parse() method for this task.
You could use string.Split() to get an array of elements separated by :. Then you can loop through it, int.Parse the elements and assign them to the integer array.
string[] buffer = startDay.Split(':');
int[] array = new int[buffer.Length];
for (int i = 0; i < buffer.Length; i++)
{
array[i] = int.Parse(buffer[i]);
}
Or you can use Linq's Select() to do the parsing.
int[] array = startDay.Split(':').Select(e => int.Parse(e)).ToArray();
Use Regex.Matches(string input, string pattern) like this:
var results = Regex.Matches(startDay, #"\d+");
var array = (from Match match in results
select Convert.ToInt32(match.Value))
.ToArray();
Instead regular expression, you can use TimeSpan.Parse()
Check it https://learn.microsoft.com/pl-pl/dotnet/api/system.timespan.parse?view=netframework-4.8
RegEx way:
var pattern = #"(\d{1,2})\s?\:\s?(\d{1,2})\s?\:\s?(\d{1,2})";
var input = "06 : 11 : 33";
var arr = Regex.Matches(input, pattern)
.Cast<Match>()
.SelectMany(x => x.Groups.Cast<Group>()
.Skip(1)
.Select(y => int.Parse(y.Value)))
.ToArray();
Console.WriteLine(string.Join("\n", arr));
The output:
06
11
33
regex101
If you have date as simple string you can use split method:
string dataString = "06 : 11 : 33";
string[] arrayStr = dataString.Split(':');
Then you can make int list using System.Linq:
List<int> intList = arrayStr.Select(p => Convert.ToInt32(p)).ToList();

Find an integer value inside a string

I'm looking to find the integer value inside the following string:
"value="5412304756756756756756792114343986"
How can I do this using C#?
You can use a regex to find the number in a string:
var resultString = Regex.Match(subjectString, #"\d+").Value;
For negative values:
var resultString = Regex.Match(yourString, #"(|-)\d+").Value;
You can look for the equals sign...
string yourString = "value=5412304756756756756756792114343986";
string integerPart = yourString.Split('=')[1];
You can use char.IsDigit
Something like .
string str = "value=5412304756756756756756792114343986";
List<char> justDigits = new List<char>();
foreach(char c in str)
{
if (char.IsDigit(c))
justDigits.Add(c);
}
string intValues = new string(justDigits.ToArray());
Or Shorter version
string intValues = new string(str.Where(char.IsDigit).ToArray());
You can use Regex:
int IntVal = Int32.Parse(Regex.Match(yourString, #"(|-)\d+").Value);
This will match negative numbers too. You could also iterate over every character in string and check id they are numerical but not really desirable solution because it can be a bottleneck.
Edit: In your input number is larger than long. For numbers like this, you can use BigInteger, from framework 4.0 onwards
Match match = new Regex("[0-9]+").Match("value=\"5412304756756756756756792114343986\"");
while(match.Success)
{
// Do something
match = match.NextMatch();
}

How do I determine if there are two or one numbers at the start of my string?

How can I determine what number (with an arbitrary number of digits) is at the start of a string?
Some possible strings:
1123|http://example.com
2|daas
Which should return 1123 and 2.
Use a regular expression:
using System.Text.RegularExpressions;
str = "35|http:\/\/v10.lscache3.c.youtube.com\/videoplayback...";
Regex r = new Regex(#"^[0-9]{1,2}");
Match m = r.Match(str);
if(m.Success) {
Console.WriteLine("Matched: " + m.Value);
} else {
Console.WriteLine("No match");
}
will capture 1-2 digits at the beginning of the string.
You can use LINQ:
string s = "35|...";
int result = int.Parse(new string(s.TakeWhile(char.IsDigit).ToArray()));
or (if the number is always followed by a |) good ol' string manipulation:
string s = "35|...";
int result = int.Parse(s.Substring(0, s.IndexOf('|')));
if you know that the number is always going to be 2 digits:
string str = "35|http:\/\/v10.lscache3.c.youtube.com\/videoplayback?...";
int result;
if (!int.TryParse(str.Substring(0, 2), out result)) {
int.TryParse(str.Substring(0, 1), out result)
}
// use the number
if you're not sure how long the number is, look at the .indexOf() approach by dtb. If you need something much more complex, only then consider using regex.
You can get the two first characters and convert to int.
var s = "a35|...";
short result = 0;
bool isNum = Int16.TryParse(s.Substring(0, 2), out result);

String parsing, extracting numbers and letters

What's the easiest way to parse a string and extract a number and a letter? I have string that can be in the following format (number|letter or letter|number), i.e "10A", "B5", "C10", "1G", etc.
I need to extract the 2 parts, i.e. "10A" -> "10" and "A".
Update: Thanks to everyone for all the excellent answers
Easiest way is probably to use regular expressions.
((?<number>\d+)(?<letter>[a-zA-Z])|(?<letter>[a-zA-Z])(?<number>\d+))
You can then match it with your string and extract the value from the groups.
Match match = regex.Match("10A");
string letter = match.Groups["letter"].Value;
int number = int.Parse(match.Groups["number"].Value);
The easiest and fastest is to use simple string operations. Use the IsDigit method to check where the letter is, and parse the rest of the string to a number:
char letter = str[0];
int index = 1;
if (Char.IsDigit(letter)) {
letter = str[str.Length - 1];
index = 0;
}
int number = int.Parse(str.Substring(index, str.Length - 1));
Just to be different:
string number = input.Trim("ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray());
string letter = input.Trim("0123456789".ToCharArray());
char letter = str.Single(c => char.IsLetter(c));
int num = int.Parse(new string(str.Where(c => char.IsDigit(c)).ToArray()));
This solution is not terribly strict (it would allow things like "5A2" and return 'A' and 52) but it may be fine for your purposes.
Here is how I would approach this. You can step through this and put gc1["letter"], gc1["number"], gc2["letter"], and gc2["number"] in the watch window to see that it worked (step just past the last line of code here, of course).
The regular epxression will take either pattern requiring one or more letter and number in each case.
Regex pattern = new Regex("^(?<letter>[a-zA-Z]+)(?<number>[0-9]+)|(?<number>[0-9]+)(?<letter>[a-zA-Z]+)$");
string s1 = "12A";
string s2 = "B45";
Match m1 = pattern.Match(s1);
Match m2 = pattern.Match(s2);
GroupCollection gc1 = m1.Groups;
GroupCollection gc2 = m2.Groups;
Using Sprache and some Linq kung-fu:
var tagParser =
from a in Parse.Number.Or(Parse.Letter.Once().Text())
from b in Parse.Letter.Once().Text().Or(Parse.Number)
select char.IsDigit(a[0]) ?
new{Number=a, Letter=b} : new{Number=b, Letter=a};
var tag1 = tagParser.Parse("10A");
var tag2 = tagParser.Parse("A10");
tag1.Letter; // should be A
tag1.Number; // should be 10
tag2.Letter; // should be A
tag2.Number; // should be 10
/* Output:
A
10
A
10
*/

Categories