meds
meds

Reputation: 22966

Iterating through string?

Not entirely sure this is possible, but say I have two strings like so:

"IAmAString-00001"
"IAmAString-00023"

What would be a quick'n'easy way to iterate from IAmAString-0001 to IAmAString-00023 by moving up the index of just the numbers on the end?

The problem is a bit more general than that, for example the string I could be dealing could be of any format but the last bunch of chars will always be numbers, so something like Super_Confusing-String#w00t0003 and in that case the last 0003 would be what I'd use to iterate through.

Any ideas?

Upvotes: 4

Views: 10375

Answers (8)

MikeTeeVee
MikeTeeVee

Reputation: 19422

If the last X numbers are always digits, then:

int x = 5;
string s = "IAmAString-00001";
int num = int.Parse(s.Substring(s.Length - x, x));
Console.WriteLine("Your Number is: {0}", num);

If the last digits can be 3, 4, or 5 in length, then you will need a little more logic:

int x = 0;
string s = "IAmAString-00001";
foreach (char c in s.Reverse())//Use Reverse() so you start with digits only.
{
    if(char.IsDigit(c) == false)
        break;//If we start hitting non-digit characters, then exit the loop.
    ++x;
}
int num = int.Parse(s.Substring(s.Length - x, x));
Console.WriteLine("Your Number is: {0}", num);

I'm not good with complicated RegEx. Because of this, I always shy away from it when maximum optimization is unnecessary. The reason for this is RegEx doesn't always parse strings the way you expect it to. If there is and alternate solution that will still run fast then I'd rather go that route as it's easier for me to understand and know that it will work with any combination of strings.

For Example: if you use some of the other solutions presented here with a string like "I2AmAString-000001", then you will get "2000001" as your number instead of "1".

Upvotes: 2

spender
spender

Reputation: 120528

You could use a Regex:

var match=Regex.Match("Super_Confusing-String#w00t0003",@"(?<=(^.*\D)|^)\d+$");
if(match.Success)
{
    var val=int.Parse(match.Value);
    Console.WriteLine(val);
}

To answer more specifically, you could use named groups to extract what you need:

var match=Regex.Match(
    "Super_Confusing-String#w00t0003",
    @"(?<prefix>(^.*\D)|^)(?<digits>\d+)$");

if(match.Success)
{
    var prefix=match.Groups["prefix"].Value;
    Console.WriteLine(prefix);
    var val=int.Parse(match.Groups["digits"].Value);
    Console.WriteLine(val);
}

Upvotes: 3

Raja
Raja

Reputation: 3618

I think it would be better if you do the search from the last (Rick already upvoted you since it was ur logic :-))

static void Main(string[] args)
    {
        var s = "IAmAString-00001";
        int index = -1;
        for (int i = s.Length - 1; i >=0; i--)
        {
            if (!char.IsDigit(s[i]))
            {
                index = i;
                break;
            }
        }
        if (index == -1)
            Console.WriteLine("digits not found");
        else
            Console.WriteLine("digits: {0}", s.Substring(index));
        Console.ReadKey();
    }

HTH

Upvotes: 2

adrianm
adrianm

Reputation: 14736

string start = "IAmAString-00001";
string end = "IAmAString-00023";

// match constant part and ending digits
var matchstart = Regex.Match(start,@"^(.*?)(\d+)$");
int numberstart = int.Parse(matchstart.Groups[2].Value);

var matchend = Regex.Match(end,@"^(.*?)(\d+)$");
int numberend = int.Parse(matchend.Groups[2].Value);

// constant parts must be the same
if (matchstart.Groups[1].Value != matchend.Groups[1].Value)
    throw new ArgumentException("");

// create a format string with same number of digits as original
string format = new string('0', matchstart.Groups[2].Length);

for (int ii = numberstart; ii <= numberend; ++ii)
    Console.WriteLine(matchstart.Groups[1].Value + ii.ToString(format));

Upvotes: 3

Tim Coker
Tim Coker

Reputation: 6524

This function will find the trailing number.

private int FindTrailingNumber(string str)
{
    string numString = "";
    int numTest;
    for (int i = str.Length - 1; i > 0; i--)
    {
        char c = str[i];
        if (int.TryParse(c.ToString(), out numTest))
        {
            numString = c + numString;
        }
    }
    return int.Parse(numString);
}

Assuming all your base strings are the same, this would iterate between strings.

string s1 = "asdf123";
string s2 = "asdf127";
int num1 = FindTrailingNumber(s1);
int num2 = FindTrailingNumber(s2);

string strBase = s1.Replace(num1.ToString(), "");

for (int i = num1; i <= num2; i++)
{
    Console.WriteLine(strBase + i.ToString());
}

Upvotes: 2

Yaur
Yaur

Reputation: 7452

string.Format and a for loop should do what you want.

for(int i = 0; i <=23; i++)
{
    string.Format("IAmAString-{0:D4}",i);
}

or something close to that (not sitting in front of a compiler).

Upvotes: 6

IndigoDelta
IndigoDelta

Reputation: 1481

If you can assume that the last 5 characters are the number then:

string prefix = "myprefix-";
for (int i=1; i <=23; i++)
{
  Console.WriteLine(myPrefix+i.ToString("D5"));
}

Upvotes: 2

Rick Sladkey
Rick Sladkey

Reputation: 34250

You can use char.IsDigit:

    static void Main(string[] args)
    {
        var s = "IAmAString-00001";
        int index = -1;
        for (int i = 0; i < s.Length; i++)
        {
            if (char.IsDigit(s[i]))
            {
                index = i;
                break;
            }
        }
        if (index == -1)
            Console.WriteLine("digits not found");
        else
            Console.WriteLine("digits: {0}", s.Substring(index));
    }

which produces this output:

digits: 00001

Upvotes: 6

Related Questions