user987316
user987316

Reputation: 942

Get Second to last character position from string

I have a dynamically formed string like - part1.abc.part2.abc.part3.abc

In this string I want to know position of second to last "." so that i can split string as part1.abc.part2.abc and part3.abc

let me know is there any direct method available to get this?

Upvotes: 6

Views: 37790

Answers (11)

Stefan Anghel
Stefan Anghel

Reputation: 194

here's a my (tested) version

/// <summary>
///     Returns the index of the <paramref name="n" />th last occurrence of <paramref name="character" /> in <paramref name="targetString" />.
///     If <paramref name="character" /> does not occur in <paramref name="targetString" />, returns -1
/// </summary>
public static int NthLastIndexOf(this string targetString, char character, int n)
{
    switch (n)
    {
        case < 1: {
            return -1;
        }
        case 1: {
            return targetString.LastIndexOf(character);
        }
        default: {
            var source = targetString[..targetString.LastIndexOf(character)];
            var resultIndex = -1;
            for (var i = 2; i <= n; i++)
            {
                var nThIndexOf = source.LastIndexOf(character);
                if (nThIndexOf == -1)
                {
                    break;
                }

                resultIndex = nThIndexOf;
                source = targetString[..nThIndexOf];
            }

            return resultIndex;
        }
    }
}

Upvotes: 0

Andrew
Andrew

Reputation: 13221

You can use the String.LastIndexOf('.') method to get the position of the last full-stop/period, then use that position in a second call to LastIndexOf('.') to get the last but one, e.g.:

string aString = "part1.abc.part2.abc.part3.abc";
int lastPos = aString.LastIndexOf('.');

int lastPosButOne = aString.LastIndexOf('.', lastPos - 1);

But I'd recommend using String.Split('.') which will give you an array of the string parts, then you can take the last but one, e.g.

string aString = "part1.abc.part2.abc.part3.abc";
string[] parts = aString.Split('.');

string lastPartButOne = parts[parts.Length - 1];

Upvotes: 8

Jamaxack
Jamaxack

Reputation: 2460

Here is another solution:

         string aString = "part1.abc.part2.abc.part3.abc";
        // Getting string until last dot
        var untilLastDot = aString.Substring(0, aString.LastIndexOf("."));
        // Now we have string until last dot and last dot here will be last but one 
        // and getting text from last but one dot to end
        string lastWordButOne = aString.Substring(untilLastDot.LastIndexOf(".") + 1);
        // Result: part3.abc

hope helps, Thanks!

Upvotes: 4

Irshad
Irshad

Reputation: 3131

Based on @bitbonk's answer. I used below code which is a replica of RAT() function of VFP.

    public static int RightIndexAt(this string expressionToSearch, char charToSearch, int occurence)
    {
        //Validate parameter
        if (occurence < 1)
            return -1;

        int index = -1;
        int numfound = 0;

        for (int count = expressionToSearch.Length - 1; count >= 0; count--)
        {
            if (expressionToSearch[count].Equals(charToSearch))
            {
                index = count;
                numfound++;
            }

            if (numfound.Equals(occurence))
                break;
        }

        return numfound < occurence ? -1 : index;
    }

Upvotes: 1

xanatos
xanatos

Reputation: 111850

string str = "part1.abc.part2.abc.part3.abc";
int ix1 = str.LastIndexOf('.');
int ix2 = ix1 > 0 ? str.LastIndexOf('.', ix1 - 1) : -1;

There are always lovers of Regexes (and jQuery), so I'll give a Regex solution (for the jQuery solution you'll have to wait :-) ):

var match = Regex.Match(str, @"\.[^\.]*\.", RegexOptions.RightToLeft);
int ix = match.Success ? match.Index : -1;

(note that I'm an hater of Regexes, I'm giving it to you so that you can have enough rope to hang yourself if you so choose).

Be aware that I'm using the RegexOptions.RightToLeft option so that the Regex starts at the last character.

Upvotes: 17

bitbonk
bitbonk

Reputation: 49609

This would be the solution, with the best possible performance (it probably won't get much faster and memory lightweight than this, unless you want to go the unsafe route):

public static int LastIndexOf(this string str, char charToSearch, int repeatCound)
{
    int index = -1;
    for(int i = str.Length - 1; i >= 0, numfound < repeatCound)
    {
        if(str[i] == charToSearch)
        {
            index = i; 
            numfound++;
        }
    }

    return index;
}

Upvotes: 0

Vala
Vala

Reputation: 5674

LastIndexOf should do what you want. Just do it twice.

Upvotes: 1

flq
flq

Reputation: 22849

As far as I know there is no out-of-the-box solution. One approach would be to find the last "." with string's LastIndexOf, and then search for the last point again, this time using the overload that lets you specify the startindex and count, using the index of the first call as parameter to count.

Upvotes: 2

Ginka
Ginka

Reputation: 570

What about "part1.abc.part2.abc.part3.abc".Split('.') in this case you will get an Array of all the substrings

Hope this helps.

Upvotes: 1

Prashant
Prashant

Reputation: 966

Try string class LastIndexOf method.

Upvotes: 1

Antoine
Antoine

Reputation: 5245

You can use String.Split() method, which returns an array of the splitted items. You can then concatenate the first 2 and leave the last one.

Upvotes: 1

Related Questions