Strings - Capitalize!

split()의 인수에 공백 문자열을 주고 ''.join을 써주면 다수의 공백도 그대로 보존된다는 걸 알게 된 문제.

문제 풀이

문제 해석

  • 사람들의 여권 속 성과 이름을 받으면 첫 글자를 대문자로 처리하도록 요청받았다.

Input Format

  • full name을 담은 string, S를 한 줄로 입력받는다.

문제 풀이

이미 주어진 코드 해석

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import math
import os
import random
import re
import sys

# Complete the solve function below.
def solve(s):

if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
s = input()
result = solve(s)
fptr.write(result + '\n')
fptr.close()

  • 온갖 모듈을 다 import하길래 여기에 낚여서 정규표현식을 쓰는 접근을 함…
  • OUTPUT_PATH 이건 또 뭔지 모르겟지만 일단 s에 할당한 인풋을 인수로 넣으면 대문자로 첫 글자를 바꾸어 반환해주는 함수를 만들어야 한다.

시행착오

  • 가장 원시적으로는 for문을 하나하나 돌리면서 첫 글자인지 확인하는 if문을 쓰고 replace 메서드로 방법도 있지만 난 이제 그정도 수준은 졸업한 것 같다.
  • 그러나 그보다 더 나은 대안도 딱히 떠오르지 않고 정규표현식으로 앞글자가 알파벳이 아니거나 처음 시작하는 글자이면 바꿔주는 re.sub 밖엔 생각이 나지 않았다.
    1
    2
    3
    4
    5
    6
    def capitalize_matchobj(match_object):
    return match_object.group().upper()

    def solve(s):
    sub_s = re.sub(r'(?<=\s)[a-z]|^[a-z]', capitalize_matchobj, s)
    return sub_s
    • 그러다보니 이런 호러블한 코드가 나왔다. match object 처리를 해줘야하기 때문에 sub에 넣을 repl에 넣을 함수를 따로 정의하는 완전 비효율적인 접근… (아마 이거 잘 처리하는 방법이 있을텐데 지금으로서는 모르겠다)
  • 그러던 중에 capitalize라는 메서드가 있다는 것도 알게 되었지만, 여러 단어가 있어도 맨 첫 단어의 앞 글자만 대문자로 변환해주기 때문에 단어를 split으로 쪼개 capitalize한 후 다시 join해주었다.
  • 분명 문제는 여권에 있는 이름이라고 했으면서 공백이 두개나 존재하는 이상한 case를 주어서 공백 두개 이상인 경우를 처리하지 못하고 discussions를 컨닝.
    • 무림고수들이 정말 많아 겸손해졌다. 그 중의 몇몇 솔루션을 소개한다.

list comprehension 활용

1
2
3
def solve(s):
split_str = s.split(' ')
return ' '.join([word.capitalize() for word in a_string])
  • split을 할 때부터 공백으로 하면 공백들도 보존이 된다는 것을 이제야 깨달았다.

map 함수에 str 객체 메서드 활용

1
2
def solve(s):
return ' '.join(map(str.capitalize, s.split(' ')))
  • capitalize 앞에만 대상 문자열을 넣을 수 있는 줄 알았는데 str에 메서드를 호출하면서 대상 문자열을 인수로 넣어줄 수도 있는 거였다.
  • 이를 콜백함수로 넣은 map에 아까처럼 공백을 기준으로 split하여 한줄로 끝냈다.

느낀 점

  • 한줄로 끝내는 끝판왕 앞에서 겸손해졌다.
  • str.capitalize처럼 str이라는 객체에 메서드를 호출하는 방식도 잘 알아두어야겠다.