2

I'm trying to split and organize a string in a single function, my goal is to seperate lowercase and uppercase characters and then return a new string essentially like so:

    "lowercasestring" + " " + "uppercasestring". 

Importantly all characters must return in the order they were recieved but split up. My problem is that i have to do this recursively in a single function(for educational purposes) and i struggle to understand how this is doable without an external function calling the recursive and then modifying the string.

    def split_rec(string):
        if string == '':                                                     
            return "-"                                                     #used to seperate late
        elif str.islower(string[0]) or string[0] == "_" or string[0] == ".": #case1
            return string[0] + split_rec(string[1:])
        elif str.isupper(string[0]) or string[0] == " " or string[0] == "|": #case2
            return split_rec(string[1:]) + string[0]
        else:                                                                #discard other
            return split_rec(string[1:])

    def call_split_rec(string):  
    ##Essentially i want to integrate the functionality of this whole function into the recursion
        mystring = split_rec(string)
        left, right = mystring.split("-")
        switch_right = right[::1]
        print(left + " " + switchright)

The recursion alone would return:

    "lowerUPPERcaseCASE" -> "lowercase" + "ESACREPPU"

My best attempt at solving this in a single function was to make case2:

    elif str.isupper(string[-1]) or string[-1] == " " or string[-1] == "|": #case2
        return split_rec(string[:-1]) + string[-1]

So that the uppercase letters would be added with last letter first, in order to correctly print the string. The issue here is that i obviously just get stuck when the first character is uppercase and the last one is lowercase.

I've spent alot of time trying to figure out a good solution to this, but im unable and there's no help for me to be found. I hope the question is not too stupid - if so feel free to remove it. Thanks!

4 Answers 4

1

I wouldn't do this recursively, but I guess you don't have a choice here. ;)

The simple way to do this in one function is to use a couple of extra arguments to act as temporary storage for the lower and upper case chars.

def split_rec(s, lo='', up=''):
    ''' Recursively split s into lower and upper case parts '''
    # Handle the base case: s is the empty string
    if not s: 
        return lo + ' ' + up

    #Otherwise, append the leading char of s 
    # to the appropriate destination...
    c = s[0]
    if c.islower():
        lo += c
    else:
        up += c
        # ... and recurse
    return split_rec(s[1:], lo, up)

# Test

print(split_rec("lowerUPPERcaseCASE"))

output

lowercase UPPERCASE

I have a couple of comments about your code.

It's not a great idea to use string as a variable name, since that's the name of a standard module. It won't hurt anything, unless you want to import that module, but it's still potentially confusing to people reading your code. The string module doesn't get a lot of use these days, but in the early versions of Python the standard string functions lived there. But then the str type inherited those functions as methods, making the old string functions obsolete.

And on that note, you generally should call those str methods as methods, rather than as functions. So don't do:

str.islower(s[0])

instead, do

s[0].islower()
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the help! Simply adding additional arguments to the recursive function was the kind of simple solution i was overlooking. Your comments about my code are also greatly appreciated, there are alot of smaller things like that im still missing.
1

Another take with recursive helper functions

def f(s):
    def lower(s):
        if not s:
            return ''
        c = s[0] if s[0].islower() else ''
        return c + lower(s[1:])
    def upper(s):
        if not s:
            return ''
        c = s[0] if s[0].isupper() else ''
        return c + upper(s[1:])
    return lower(s) + ' ' + upper(s)

Comments

1

The easiest way would be to use sorted with a custom key:

>>> ''.join(sorted("lowerUPPERcaseCASE" + " ", key=str.isupper))
'lowercase UPPERCASE'

There's really no reason to use any recursive function here. If it's for educational purpose, you could try to find a problem for which it's actually a good idea to write a recursive function (fibonacci, tree parsing, merge sort, ...).

As mentioned by @PM2Ring in the comments, this sort works fine here because Python sorted is stable: when sorting by case, letters with the same case stay at the same place relative to one another.

6 Comments

Sure, but that's not recursive.
@PM2Ring: There's 0 reason to write a recursive function here. The correct answer to "How do I cut a woodenboard in two with a hammer?" is "Use a saw", not "Apply more pressure with the hammer".
Yes even i understand this problem is very poorly fit for a recursive solution, i could solve the problem easily using iteration. The solution you give looks very nice for when i actually do need to be efficient, thanks. But like i said the problem was moreso about my poor understanding of how to make recursion work in this instance than it was about solving the actual problem.
There's 1 reason to use recursion: that's what the OP stated in the question. ;) Generally that means they're doing homework, and they have to use recursion because that's what they're currently studying. But of course it's also possible that the OP is self-studying, and not being forced to use recursion by their teacher. I fully agree that normally one should only use recursion in Python when it's appropriate for the problem domain (like dealing with a recursive data structure); OTOH, there's no harm in learning how to use recursion in cases where it's not the natural approach.
@cmnty BTW, Eric's solution works because Python's sort function, TimSort, is stable, so you can perform sorts in multiple stages and each stage won't unduly disturb the results of the previous stages.
|
0

Here is a way to do it with only the string as parameter:

def split_rec(s):
    if not '|' in s:
        s = s + '|'

    if s.startswith('|'):                                                     
            return s.replace('|', ' ')

    elif s[0].islower():
        return s[0] + split_rec(s[1:])

    elif s[0].isupper():
        # we move the uppercase first letter to the end
        s = s[1:] +  s[0]
        return split_rec(s)
    else:                                                                
            return split_rec(s[1:])

split_rec('aAbBCD')
# 'ab ABCD'

The idea is:

  • We add a marker at the end (I chose |)
  • If the first char is lowercase, we return it + the organized rest
  • If it is uppercase, we move it to the end, and reorganize the whole string
  • We stop once we reach the marker: the current string is the marker followed by the organized uppercase letters. We replace the marker by a space and return it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.