384

What's the recommended Python idiom for splitting a string on the last occurrence of the delimiter in the string? example:

# instead of regular split
>> s = "a,b,c,d"
>> s.split(",")
>> ['a', 'b', 'c', 'd']

# ..split only on last occurrence of ',' in string:
>>> s.mysplit(s, -1)
>>> ['a,b,c', 'd']

mysplit takes a second argument that is the occurrence of the delimiter to be split. Like in regular list indexing, -1 means the last from the end. How can this be done?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343

3 Answers3

652

Use .rsplit() or .rpartition() instead:

s.rsplit(',', 1)
s.rpartition(',')

str.rsplit() lets you specify how many times to split, while str.rpartition() only splits once but always returns a fixed number of elements (prefix, delimiter & postfix) and is faster for the single split case.

Demo:

>>> s = "a,b,c,d"
>>> s.rsplit(',', 1)
['a,b,c', 'd']
>>> s.rsplit(',', 2)
['a,b', 'c', 'd']
>>> s.rpartition(',')
('a,b,c', ',', 'd')

Both methods start splitting from the right-hand-side of the string; by giving str.rsplit() a maximum as the second argument, you get to split just the right-hand-most occurrences.

If you only need the last element, but there is a chance that the delimiter is not present in the input string or is the very last character in the input, use the following expressions:

# last element, or the original if no `,` is present or is the last character
s.rsplit(',', 1)[-1] or s
s.rpartition(',')[-1] or s

If you need the delimiter gone even when it is the last character, I'd use:

def last(string, delimiter):
    """Return the last element from string, after the delimiter

    If string ends in the delimiter or the delimiter is absent,
    returns the original string without the delimiter.

    """
    prefix, delim, last = string.rpartition(delimiter)
    return last if (delim and last) else prefix

This uses the fact that string.rpartition() returns the delimiter as the second argument only if it was present, and an empty string otherwise.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Worth noting the the `rsplit` is bound to fail if the delimiter does NOT exist within the target string. In which case I suggest using the fairly similar `s.split('delimiter')[-1]` which works in both cases - whether the delimiter exists or not within the string. – roy650 May 01 '22 at 12:53
  • @roy650: No, `rsplit()` will *not* fail, and using `s.split()` instead can create a huge amount of wasted objects; it is *completely not necessary* as `s.rsplit('delimiter', 1)[-1]` would work just the same. Note that `s.rpartition()` gives you 3 strings, every time, guaranteed, but the second and third could be empty strings, and so `s.rpartition(',')[-1] or s` would give you the last element or the original. That same expression works for `s.rsplit()` and *both would produce the original if `s` **ends** in a comma*. – Martijn Pieters May 01 '22 at 12:59
  • @roy650: try it yourself: `'foo'.rsplit(',', 1)[-1]` produces `'foo'`. Also try `'foo,'.rsplit(',', 1)[-1] or 'foo,'`, and `'foo,'.rpartition(',')[-1] or 'foo,'`. – Martijn Pieters May 01 '22 at 13:27
43

You can use rsplit

string.rsplit('delimeter',1)[1]

To get the string from reverse.

Wickkiey
  • 4,446
  • 2
  • 39
  • 46
5

I just did this for fun

    >>> s = 'a,b,c,d'
    >>> [item[::-1] for item in s[::-1].split(',', 1)][::-1]
    ['a,b,c', 'd']

Caution: Refer to the first comment in below where this answer can go wrong.

ViKiG
  • 764
  • 9
  • 21
  • 4
    'just for fun' but also very wrong, because if the delimiter is not just a single character or a repeated character, your splits will pick, at best, the wrong points to split on. – Martijn Pieters Feb 12 '20 at 14:23