Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find second occurence from the right of a character, without iteration

I have a Python string:

test = 'blablabla_foo_bar_baz'

I want the negative index of the second occurence from the right of _: in this case, this would be -8, but even 13, the positive index, would be an acceptable answer, because it's not hard to compute the negative index from the positive index. How can I do that? A GPT-4 solution uses rfind + iteration, but I was wondering if it could be possible to solve it in one shot, without iteration. Of course the answer should handle strings of arbitrary length, and it should match an arbitrary character (_ in this example).

EDIT: I need the negative index of the second occurence from the right of _, because I want to strip away _bar_baz, which can be done easily with

test_prefix = test[:-8]

Thus, alternative solutions that allow me to get test_prefix without first finding the negative index of the second occurence from the right of _, would also be ok. Using the length of the substring _bar_baz (8 in this case) is not ok because I don't know the length of this substring. Instead computing the length of the substring from the second occurrence from the right of _, until the end of the string, would be ok. It doesn't seem any different from computing he negative index of the second occurence from the right of _, though.

EDIT2: a commenter says that it's impossible to solve this without iteration. I'm not sure they're right, but I'll show a (GPT-4-generated) example of what I don't want:

def find_second_last_occurrence(text, char='_'):
    last_occurrence = text.rfind(char)

    second_last_occurrence = text.rfind(char, 0, last_occurrence)

    return second_last_occurrence

string = "blablabla_foo_bar_baz"
result = find_second_last_occurrence(string, '_')

print(result)  # Output: 20

In this case, we had to call rfind twice. Is this really necessary? I don't think all possible solutions (including those based on re, rsplit, etc.) require calling a builtin twice. Note that I didn't include any code checking for the occurence of _ in the string, because I know for sure that my input string contains at least two occurences of _.

like image 272
DeltaIV Avatar asked Oct 29 '25 22:10

DeltaIV


1 Answers

I am unsure the exact solution that is wanted but if the goal is just to split the string there is a much cleaner approach which can also give you the index it was cut at.

test = 'blablabla_foo_bar_baz'
result, *_ = test.rsplit('_', maxsplit=2) # split from the right two times
print(result) # blablabla_foo
print(len(result)) # 13 which is the index it was cut off at
print(len(test) - len(result)) # 8 i.e. the negative index
like image 159
Error - Syntactical Remorse Avatar answered Oct 31 '25 11:10

Error - Syntactical Remorse