KingFish
KingFish

Reputation: 9183

Remove Last instance of a character and rest of a string

If I have a string as follows:

foo_bar_one_two_three

Is there a clean way, with RegEx, to return: foo_bar_one_two?

I know I can use split, pop and join for this, but I'm looking for a cleaner solution.

Upvotes: 16

Views: 28364

Answers (5)

rouble
rouble

Reputation: 18241

Here is a generic function to remove everything after the last occurrence of any specified string. For extra credit, it also supports removing everything after the nth last occurrence.

def removeEverythingAfterLast (needle, haystack, n=1):
    while n > 0:
        idx = haystack.rfind(needle)
        if idx >= 0:
            haystack = haystack[:idx]
            n -= 1
        else:
            break
    return haystack

In your case, to remove everything after the last '_', you would simply call it like this:

updatedString = removeEverythingAfterLast('_', yourString)

If you wanted to remove everything after the 2nd last '_', you would call it like this:

updatedString = removeEverythingAfterLast('_', yourString, 2)

Upvotes: 1

Tadeck
Tadeck

Reputation: 137450

result = my_string.rsplit('_', 1)[0]

Which behaves like this:

>>> my_string = 'foo_bar_one_two_three'
>>> print(my_string.rsplit('_', 1)[0])
foo_bar_one_two

See in the documentation entry for str.rsplit([sep[, maxsplit]]).

Upvotes: 32

nakedfanatic
nakedfanatic

Reputation: 3178

Similar the the rsplit solution, rpartition will also work:

result = my_string.rpartition("_")[0]

You'll need to watch out for the case where the separator character is not found. In that case the original string will be in index 2, not 0.

doc string:

rpartition(...)

S.rpartition(sep) -> (head, sep, tail)

Search for the separator sep in S, starting at the end of S, and return the part before it, the separator itself, and the part after it. If the separator is not found, return two empty strings and S.

Upvotes: 3

paxdiablo
paxdiablo

Reputation: 882716

One way is to use rfind to get the index of the last _ character and then slice the string to extract the characters up to that point:

>>> s = "foo_bar_one_two_three"
>>> idx = s.rfind("_")
>>> if idx >= 0:
...     s = s[:idx]
...
>>> print s
foo_bar_one_two

You need to check that the rfind call returns something greater than -1 before using it to get the substring otherwise it'll strip off the last character.

If you must use regular expressions (and I tend to prefer non-regex solutions for simple cases like this), you can do it thus:

>>> import re
>>> s = "foo_bar_one_two_three"
>>> re.sub('_[^_]*$','',s)
'foo_bar_one_two'

Upvotes: 3

unmultimedio
unmultimedio

Reputation: 1244

I know is python, and my answer may be a little bit wrong in syntax, but in java you would do:

String a = "foo_bar_one_two_three";
String[] b = a.split("_");
String c = "";
for(int i=0; i<b.length-1; a++){
    c += b[i];
    if(i != b.length-2){
        c += "_";
    }
}
//and at this point, c is "foo_bar_one_two"

Hope in python split function works same way. :)

EDIT:

Using the limit part of the function you can do:

String a = "foo_bar_one_two_three";
String[] b = a.split("_",StringUtils.countMatches(a,"_"));
//and at this point, b is the array = [foo,bar,one,two]

Upvotes: 0

Related Questions