1

I've been trying to define a function that will capitalise every other letter and also take spaces into accout for example:

print function_name("Hello world") should print "HeLlO wOrLd" rather than "HeLlO WoRlD"

I hope this makes sense. Any help is appreciated.

Thanks, Oli

Perceptic
  • 443
  • 1
  • 7
  • 19

5 Answers5

6
def foo(s):
    ret = ""
    i = True  # capitalize
    for char in s:
        if i:
            ret += char.upper()
        else:
            ret += char.lower()
        if char != ' ':
            i = not i
    return ret

>>> print foo("hello world")
HeLlO wOrLd'
vik
  • 300
  • 1
  • 12
4

I think this is one of those cases where a regular for-loop is the best idea:

>>> def f(s):
...     r = ''
...     b = True
...     for c in s:
...         r += c.upper() if b else c.lower()
...         if c.isalpha():
...             b = not b
...     return r
...
>>> f('Hello world')
'HeLlO wOrLd'
arshajii
  • 127,459
  • 24
  • 238
  • 287
  • Please do not create strings by repeatedly adding one character (`+=`). The performance is lousy. For example, try applying this to [War and Peace](http://www.gutenberg.org/files/2600/2600.txt). – Steven Rumbalski Jul 25 '13 at 18:28
  • 1
    @StevenRumbalski You misunderstand the purpose of my answer; it is only meant to show the general way in which what the OP asks for can be achieved. If the OP is working with code so performance-sensitive that such string concatenation is out of the question (a very rare case indeed), then he can look into something like mutable strings. However, the approach outlined above will remain the same. – arshajii Jul 25 '13 at 18:32
3

Here is a version that uses regular expressions:

import re

def alternate_case(s):
    cap = [False]
    def repl(m):
        cap[0] = not cap[0]
        return m.group(0).upper() if cap[0] else m.group(0).lower()
    return re.sub(r'[A-Za-z]', repl, s)

Example:

>>> alternate_case('Hello world')
'HeLlO wOrLd'
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • I suppose it is a list to avoid `global` or `nonlocal`. – Steven Rumbalski Jul 25 '13 at 18:30
  • If the code is on Python 3.x I would go with `nonlocal` instead. It has to be a list here because something like `cap = not cap` in the `repl()` function would give you a "local variable referenced before assignment" error unless `nonlocal cap` or `global cap` were used first. I don't like using `global` and `nonlocal` isn't available on Python 2.x. See http://stackoverflow.com/a/8934902/505154 – Andrew Clark Jul 25 '13 at 18:32
  • You could also use a function attribute here, between the `repl` definition and the `return re.sub(...)` you would put `repl.cap = False`, and then change every `cap[0]` reference inside of `repl` to `repl.cap`. – Andrew Clark Jul 25 '13 at 18:35
0

This should do the trick:

def function_name(input_string):
    should_capitalize = True
    chars = []
    for single_char in input_string:
        if not single_char.isalpha():
            chars.append(single_char)
            continue

        if should_capitalize:
            chars.append(single_char.upper())
        else:
            chars.append(single_char.lower())

        should_capitalize = not should_capitalize

    return ''.join(chars)
Maciej Gol
  • 15,394
  • 4
  • 33
  • 51
0

A (hopefully elegant) recursive approach:

def funky_cap(s, use_lower=False):
    if s == '':
        return s
    elif not s[0].isalpha():
        return s[0] + funky_cap(s[1:], use_lower)
    elif use_lower:
        return s[0].lower() + funky_cap(s[1:], not use_lower)
    else: # when we need an uppercase letter
        return s[0].upper() + funky_cap(s[1:], not use_lower)
Micah Walter
  • 908
  • 9
  • 19