I have a field representing an "Account Number" that is anything but a number most of the time. I need to do some auto-incrementing of these "numbers". Clearly non-ideal for doing math with. The rule that we've decided works for us is that we want to find the right-most group of numbers and auto-increment them by one and return the rebuilt string (even if this makes it one character longer).
Some examples of the numbers are:
I'm working with C#/.NET 4.0. I listed Regex as a tag but that isn't a requirement. This solution need not be in Regular Expressions.
Any thoughts on a good way to do this? Ideal performance isn't a major concern. I'd rather have clear and easy-to-understand/maintain code for this unless it's all wrapped up in a Regex.
Thanks!
var src = "ap45245jpb1234h";
var match = Regex.Match(src, @"(?<=(\D|^))\d+(?=\D*$)");
if(match.Success)
{
var number = int.Parse(match.Value) + 1;
var newNum=string.Format(
"{0}{1}{2}",
src.Substring(0,match.Index),
number,
src.Substring(match.Index + match.Length));
newNum.Dump(); //ap45245jpb1235h
}
Explaining the regex: starting either from (the start of the string) or (a non-digit), match one or more digits that are followed by zero or more non-digits then the end of the string.
Of course, if the extracted number has leading zeros, things will go wrong. I'll leave this as an exercise to the reader.
Using a MatchEvaluator (as suggested by @LB in their answer) this becomes somewhat lighter:
Regex.Replace(
src,
@"(?<=(\D|^))\d+(?=\D*$)",
m => (int.Parse(m.Value)+1).ToString())
If I understand you correctly, you would like to add one to the number which is right-most within a certain string.
You could use Regex as others suggested, but since you are trying to do something very specific, Regex will prove slower than implementing an algorithm just for what you do.
You can test this against the Regex solution, and see for yourself that this will be a lot faster:
I ran both 1 million times and timed it with Stopwatch.
Results:
Regex - 10,808,533 ticks
My way - 253,355 ticks
About 40 times faster!!!
Conclusion: Specific solutions for specific problems.
My way is A LOT faster.
And here's the code:
// Goes through a string from end to start, looking for the last digit character.
// It then adds 1 to it and returns the result string.
// If the digit was 9, it turns it to 0 and continues,
// So the digit before that would be added with one.
// Overall, it takes the last numeric substring it finds in the string,
// And replaces it with itself + 1.
private static unsafe string Foo(string str)
{
var added = false;
fixed (char* pt = str)
{
for (var i = str.Length - 1; i >= 0; i--)
{
var val = pt[i] - '0';
// Current char isn't a digit
if (val < 0 || val > 9)
{
// Digits have been found and processed earlier
if (added)
{
// Add 1 before the digits,
// Because if the code reaches this,
// It means it was something like 999,
// Which should become 1000
str = str.Insert(i + 1, "1");
break;
}
continue;
}
added = true;
// Digit isn't 9
if (val < 9)
{
// Set it to be itself + 1, and break
pt[i] = (char)(val + 1 + '0');
break;
}
// Digit is 9. Set it to be 0 and continue to previous characters
pt[i] = '0';
// Reached beginning of string and should add 1 before digits
if (i == 0)
{
str = str.Insert(0, "1");
}
}
}
return str;
}
Assuming you don't want to replace 1 digit numbers.
string input = "GS3R2C1234g";
var output = Regex.Replace(input, @"\d{2,}$*", m => (Convert.ToInt64(m.Value) + 1).ToString());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With