471,326 Members | 1,881 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,326 software developers and data experts.

Get number from end of name

I need to create function

static int ItemNumber(string itemName)

which returns number from end of name

ItemNumber("Item1") returns 1
ItemNumber("Other1") returns 1
ItemNumber("Item123") returns 123
etc.
How to create this ?

Andrus.

Aug 7 '08 #1
12 1446
On Aug 7, 12:09*pm, "Andrus" <kobrule...@hot.eewrote:
I need to create function *

static int ItemNumber(string itemName)

which returns number from end of name

ItemNumber("Item1") *returns *1
ItemNumber("Other1") *returns *1
ItemNumber("Item123") *returns *123

etc.
How to create this ?

Andrus.
Loop through the string with the .Substring method specifying one
character at at time. Try to convert the character to a number in a
Try/Catch block. When the function is successful, then from that index
position on is the number, and you can pick it off with
another .Substring call.
Aug 7 '08 #2
On Aug 7, 5:16 pm, za...@construction-imaging.com wrote:
Loop through the string with the .Substring method specifying one
character at at time.
There's no point in creating loads of strings for no reason. Using the
indexer returns a char:

char c = text[i];
Try to convert the character to a number in a
Try/Catch block.
Ick no. Use Character.IsDigit - then you're not using exceptions for
flow control.
When the function is successful, then from that index
position on is the number, and you can pick it off with
another .Substring call.
No, that would fail on "foo5bar10". We need to work back from the end.
I would suggest something like:

public static int ParseNumberAtEnd(string text)
{
for (int i = text.Length-1; i >= 0; i--)
{
if (!Character.IsDigit(text[i]))
{
if (i == text.Length - 1)
{
throw new ArgumentException("No digits at end");
}
string digits = text.Substring(i+1);
return int.Parse(digits);
}
}
// Text is entirely made of digits!
return int.Parse(text);
}

Alternatively, Andrus could use a regex of something like @"\d
+^" (Possibly $ instead of ^ - I can never remember which way round
they go.)

Jon
Aug 7 '08 #3
Alternatively, Andrus could use a regex of something like @"\d
+^" (Possibly $ instead of ^ - I can never remember which way round
they go.)
$ in this case, to anchor the end.
^ anchors the beginning.
LastIndexOfAny might also be a reasonable solution, though I would expect
Char.IsDigit to be faster.
>
Jon

Aug 7 '08 #4
Along the same lines as Jon's reply, here is a fun way if you are
using Framework 3.5:

int.Parse("0" +
item.Substring(Array.LastIndexOf<char>(item.ToChar Array(),
item.ToCharArray().LastOrDefault<char>(c =!Char.IsDigit(c))) + 1))

Long line, but nice trick. Just an FYI.
jake
On Aug 7, 12:28 pm, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
On Aug 7, 5:16 pm, za...@construction-imaging.com wrote:
Loop through the string with the .Substring method specifying one
character at at time.

There's no point in creating loads of strings for no reason. Using the
indexer returns a char:

char c = text[i];
Try to convert the character to a number in a
Try/Catch block.

Ick no. Use Character.IsDigit - then you're not using exceptions for
flow control.
When the function is successful, then from that index
position on is the number, and you can pick it off with
another .Substring call.

No, that would fail on "foo5bar10". We need to work back from the end.
I would suggest something like:

public static int ParseNumberAtEnd(string text)
{
for (int i = text.Length-1; i >= 0; i--)
{
if (!Character.IsDigit(text[i]))
{
if (i == text.Length - 1)
{
throw new ArgumentException("No digits at end");
}
string digits = text.Substring(i+1);
return int.Parse(digits);
}
}
// Text is entirely made of digits!
return int.Parse(text);

}

Alternatively, Andrus could use a regex of something like @"\d
+^" (Possibly $ instead of ^ - I can never remember which way round
they go.)

Jon
Aug 7 '08 #5
On Thu, 07 Aug 2008 10:05:18 -0700, Ben Voigt [C++ MVP]
<rb*@nospam.nospamwrote:
>Alternatively, Andrus could use a regex of something like @"\d
+^" (Possibly $ instead of ^ - I can never remember which way round
they go.)

$ in this case, to anchor the end.
^ anchors the beginning.
LastIndexOfAny might also be a reasonable solution, though I would expect
Char.IsDigit to be faster.
Of course, if faster was the priority, calling Parse() is probably not the
preferred solution anyway. Instead, one would just scan once from the end
to find the start of the numeric string, and then go forward again,
accumulating each digit and multiplying by 10 with each new one before
adding the current digit. In other words, basically the same as what
Jon's code does, but combining the substring extraction with the parsing,
and doing it all in the same method rather than calling into the classes
(and without instantiating an intermediate string). For example:

public static int ParseNumberAtEnd(string text)
{
int i = text.Length;
int result = 0;

while (--i >= 0 && Character.IsDigit(text[i])) { }

if (i == text.Length - 1)
{
throw new ArgumentException("No digits at end");
}

while (++i < text.Length)
{
result = result * 10 + text[i] - '0';
}

return result;
}

For maintainability, I like the RegEx suggestion. It keeps all the
looping/substring mechanics hidden from view, leaving just the semantics
of "parse the number at the end of the string".

I think using LastIndexOfAny() is a reasonable alternative to RegEx, if
one finds the RegEx syntax less-than-obvious, but then you'd be stuck with
the explicit call to Substring() before Parse().

How many other ways can we skin this cat? :)

Pete
Aug 7 '08 #6
"Peter Duniho" <Np*********@nnowslpianmk.comwrote:
How many other ways can we skin this cat? :)
static int GetNumberAtEnd(string s)
{
int val = 0, pos = s.Length - 1;
while (pos 0 && s[pos] >= '0' && s[pos] <= '9')
{
val += (s[pos] - '0') * (int) Math.Pow(10, s.Length - pos - 1);
pos--;
}
return val;
}

Eq.
Aug 7 '08 #7
Peter Duniho <Np*********@nnowslpianmk.comwrote:

<snip>
How many other ways can we skin this cat? :)
Create a parameterised SQL query and get the query engine to do the
work? Or we could always set up a web service for it, and maybe write a
custom LINQ provider to call that web service.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 7 '08 #8
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote:
Use Character.IsDigit
But are digits recognised by Char.IsDigit guaranteed to parse as integers?
Even on a Western system, Hebrew numerals would count as digits (in the
character sense), wouldn't they?

Eq.
Aug 7 '08 #9
Paul E Collins <fi******************@CL4.orgwrote:
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote:
Use Character.IsDigit

But are digits recognised by Char.IsDigit guaranteed to parse as integers?
Even on a Western system, Hebrew numerals would count as digits (in the
character sense), wouldn't they?
Hmm... not sure. It's only *decimal* digits, but I don't know what
other characters are in DecimalDigitNumber.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 7 '08 #10
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote:
But are digits recognised by Char.IsDigit guaranteed to parse as
integers? Even on a Western system, Hebrew numerals would count as
digits (in the character sense), wouldn't they?

Hmm... not sure. It's only *decimal* digits, but I don't know what other
characters are in DecimalDigitNumber.
char ch = (char) 0x667; // Arabic-Indic Digit Seven
Console.WriteLine(Char.IsDigit(ch)); // "True"
int i = Int32.Parse(ch.ToString()); // throws FormatException

I suppose Int32.Parse *might* work differently depending on your system
locale, but in either case Char.IsDigit will check whether the character is
a digit in *any* locale, so it's not safe to use for this purpose.

Eq.
Aug 7 '08 #11
Paul E Collins <fi******************@CL4.orgwrote:
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote:
But are digits recognised by Char.IsDigit guaranteed to parse as
integers? Even on a Western system, Hebrew numerals would count as
digits (in the character sense), wouldn't they?
Hmm... not sure. It's only *decimal* digits, but I don't know what other
characters are in DecimalDigitNumber.

char ch = (char) 0x667; // Arabic-Indic Digit Seven
Console.WriteLine(Char.IsDigit(ch)); // "True"
int i = Int32.Parse(ch.ToString()); // throws FormatException

I suppose Int32.Parse *might* work differently depending on your system
locale, but in either case Char.IsDigit will check whether the character is
a digit in *any* locale, so it's not safe to use for this purpose.
Yup. It's a shame there isn't a property for this, as it's reasonably
common.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 7 '08 #12
Jon Skeet [C# MVP] wrote:
Paul E Collins <fi******************@CL4.orgwrote:
>"Jon Skeet [C# MVP]" <sk***@pobox.comwrote:
>>>But are digits recognised by Char.IsDigit guaranteed to parse as
integers? Even on a Western system, Hebrew numerals would count as
digits (in the character sense), wouldn't they?

Hmm... not sure. It's only *decimal* digits, but I don't know what
other characters are in DecimalDigitNumber.

char ch = (char) 0x667; // Arabic-Indic Digit Seven
Console.WriteLine(Char.IsDigit(ch)); // "True"
int i = Int32.Parse(ch.ToString()); // throws FormatException

I suppose Int32.Parse *might* work differently depending on your
system locale, but in either case Char.IsDigit will check whether
the character is a digit in *any* locale, so it's not safe to use
for this purpose.

Yup. It's a shame there isn't a property for this, as it's reasonably
common.
Cue requests for extension properties.
Aug 8 '08 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Dave Merrill | last post: by
reply views Thread by johkar | last post: by
2 posts views Thread by Richard Haber | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.