user10860402
user10860402

Reputation: 1012

Get set of numbers from string without regex

"abc_d1.txt" should get 0
"abc_d1_2.txt" should get 2
"abc_d1_14.txt" should get 14
"abc_d12_x2_156.txt" should get 156

Can do this currently with regex

 int Id;
 string pattern = @"(?<=_)\d+(?=\.\w+)|(?<!_\d+)(?=\.\w+)";
 Regex rg = new Regex(pattern);
 var z = rg.Match(fullFileName).Value;
 Id = z == "" ? 0 : Convert.ToInt32(z);

But how to do it without regex?

Upvotes: 2

Views: 668

Answers (2)

Caius Jard
Caius Jard

Reputation: 74660

Classic string manipulation:

int u = s.LastIndexOf('_');
return  int.TryParse(s.Substring(u + 1, s.Length - u - 5), out int i) ? i : 0;

(Following on from the comment) - the 5 is a bit of "magic number" I guess - it's the length of the extension ".txt" 4 plus 1 to negate the effect of u being one index short (because it's pointing to the position of the underscore, not the position of the first char of the number after it). I could have written s.Substring(u + 1, s.Length - (u + 1) - 4 but this form might self-explain a little better:

int begin = s.LastIndexOf('_') + 1;
return  int.TryParse(s.Substring(begin, s.Length - begin - 4), out int i) ? i : 0;

Upvotes: 2

TheGeneral
TheGeneral

Reputation: 81523

I'm not sure why you don't want to use regex (I don't judge). However, assuming everything is exactly as you have described, and you need no validation. A low tech approach would be to just Split the string, TryParse the results, then call LastOrDefault

Given

private static int GetNumber(string input)
  => input.Split('_','.')
      .Select(x => int.TryParse(x, out var value) ? value : (int?)null)
      .LastOrDefault(x => x != null) ?? 0;

Usage

var asd = new List<string>()
{
   "abc_d1.txt",
   "abc_d1_2.txt",
   "abc_d1_14.txt",
   "abc_d12_x2_156.txt"
};

foreach (var result in asd.Select(GetNumber))
   Console.WriteLine(result);

Output

0
2
14
156

Upvotes: 5

Related Questions