在C#中提取字符串末尾的数字
Posted
技术标签:
【中文标题】在C#中提取字符串末尾的数字【英文标题】:Extract number at end of string in C# 【发布时间】:2012-10-21 14:05:12 【问题描述】:可能会稍微分析一下,但是 *** 建议如何返回包含在字符串末尾的整数的最佳方法。
到目前为止,我已经考虑过使用简单的循环、LINQ 和正则表达式,但我很好奇我会从社区中获得什么方法。显然,这不是一个很难解决的问题,但解决方案可能存在差异。
所以更具体地说,您将如何创建一个函数来返回附加在任意长字符串末尾的任意长整数/长整数?
CPR123 => 123
ABCDEF123456 => 123456
【问题讨论】:
【参考方案1】:使用这个正则表达式:
\d+$
var result = Regex.Match(input, @"\d+$").Value;
或者使用Stack
,可能更高效:
var stack = new Stack<char>();
for (var i = input.Length - 1; i >= 0; i--)
if (!char.IsNumber(input[i]))
break;
stack.Push(input[i]);
var result = new string(stack.ToArray());
【讨论】:
【参考方案2】:强制性 LINQ 单行代码
var input = "ABCD1234";
var result = string.Concat(input.ToArray().Reverse().TakeWhile(char.IsNumber).Reverse());
【讨论】:
我认为它是所有答案中最棒的一个。我在找这个。谢谢! 但IsNumber
不仅会为 0-9 ASCII 返回 true。
.ToArray() 好像是多余的【参考方案3】:
像\d+$
这样的正则表达式模式有点昂贵,因为默认情况下,字符串是从左到右解析的。一旦正则表达式引擎在12abc34
中找到1
,它就会继续匹配2
,当它遇到a
时,匹配失败,尝试下一个位置,以此类推。
但是,在 .NET 正则表达式中,有一个 RegexOptions.RightToLeft
修饰符。它使正则表达式引擎从右到左解析字符串,您可能会更快地获得已知更接近结尾的匹配项。
var result = Regex.Match("000AB22CD1234", @"\d+$", RegexOptions.RightToLeft);
if (result.Success)
Console.Write(result.Value);
// => 1234
请参阅online C# demo。
【讨论】:
【参考方案4】:就我的经验而言,正则表达式是最简单的。
Regex ex = new Regex(@"(\d+)$")
这应该匹配它。只需将其包装在一个函数中即可。
【讨论】:
正则表达式中的括号毫无意义;)(甚至会产生开销,这是 OP 想要避免的)【参考方案5】:[^0-9]+([0-9]+)
我认为应该这样做
【讨论】:
如果字符串末尾的第一个之前有整数怎么办?如果字符串末尾的整数之前没有非数字字符怎么办? 这不是他要求的,他的例子是字母然后数字。无论如何,正如我所说,基里尔的答案更好,因为它更简单并且可以处理这两种情况 嗯好吧。我将“任意长字符串”读为“任意字符串”。我猜“任意长”也包括 0 长度。 确实如此,但在这种情况下,我认为这不是他的意思,我通常会在外部检查正则表达式【参考方案6】:总是采用 LettersNumbers 格式吗?
在这种情况下,这会起作用:
Regex _cellAddressRegex = new Regex(@"(?<Column>[a-z]+)(?<Row>[0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
var rowm = Convert.ToInt32(parts.Groups["Row"]);
【讨论】:
我不会使用Compiled
选项。将正则表达式编译为 MSIL 需要付出大量的前期成本,但据您所知,它只会使用一次,而且它非常简单,可能无论如何都不会从优化中受益。
确实如此。我从我的一个代码库中提取了它,但有一次它没有。【参考方案7】:
我可以为此发疯吗?
using System.Text;
using System.Linq;
static string GetNum(string input)
StringBuilder sb = new StringBuilder();
for (int i = input.Length - 1; i >= 0; i--)
if (input[i] < 48 || input[i] > 57)
break;
sb.Append(input[i]);
return String.Concat(sb.ToString().ToCharArray().Reverse());
【讨论】:
【参考方案8】:一个简单的循环可能在其简单性和效率方面胜过任何其他解决方案。并且最终返回的字符串可以只复制一次,而无需使用 Stack、StringBuilder、string.Concat 或其他更复杂的字符串支持函数。
string GetNumberFromEnd(string text)
int i = text.Length - 1;
while (i >= 0)
if (!char.IsNumber(text[i])) break;
i--;
return text.Substring(i + 1);
或者甚至可以直接作为int类型返回:
bool GetIntFromEnd(string text, out int number)
int i = text.Length - 1;
while (i >= 0)
if (!char.IsNumber(text[i])) break;
i--;
return int.TryParse(text.Substring(i + 1), out number);
【讨论】:
【参考方案9】:不使用难以理解的 RegEx,或者可能很慢的 Linq 和数组操作,可以使用扩展方法中的简单循环。
它可以用于long
或int
或ulong
或uint
或其他同时适应+
和-
检查。
它也可以适应解析float
和double
或decimal
。
这个方法也可以写成Parse
有异常。
实施
static public class StringHelper
static public bool TryParseEndAsLong(this string str, out long result)
result = 0;
if ( string.IsNullOrEmpty(str) )
return false;
int index = str.Length - 1;
for ( ; index >= 0; index-- )
char c = str[index];
bool stop = c == '+' || c == '-';
if ( !stop && !char.IsDigit(c) )
index++;
break;
if ( stop )
break;
return index <= 0 ? long.TryParse(str, out result)
: long.TryParse(str.Substring(index), out result);
测试
test(null);
test("");
test("Test");
test("100");
test("-100");
test("100-200");
test("100 - 200");
test("Test 100");
test("Test100");
test("Test+100");
test("Test-100");
test("11111111111111111111");
Action<string> test = str =>
if ( str.TryParseEndAsLong(out var value) )
Console.WriteLine($"\"str\" => value");
else
Console.WriteLine($"\"str\" has not a long at the end");
;
输出
"" has not a long at the end
"" has not a long at the end
"Test" has not a long at the end
"100" => 100
"-100" => -100
"100-200" => -200
"100 - 200" => 200
"Test 100" => 100
"Test100" => 100
"Test+100" => 100
"Test-100" => -100
"11111111111111111111" has not a long at the end
【讨论】:
以上是关于在C#中提取字符串末尾的数字的主要内容,如果未能解决你的问题,请参考以下文章