문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.
| s | return |
|---|---|
| "try hello world" | "TrY HeLlO WoRlD" |
def solution(s):
answer = ''
idx = 0
for c in s:
if c == ' ':
idx = 0
answer += ' '
# 짝
elif idx % 2 == 0:
answer += c.upper()
idx += 1
# 홀
elif idx % 2 == 1:
answer += c.lower()
idx += 1
return answer
이 문제의 핵심은 문자열 내 인덱스가 아닌, 공백을 기준으로 나뉜 문자열, 즉 단어 내의 순서에 따라 대소문자 여부가 결정되었다. 또한 공백은 1개가 아닌, 1개 이상이었다는 점이 문제였다.
따라서, 나에게는 단어별 인덱스가 필요했다. 문자열 s를 순회하면서 공백인 경우, 인덱스를 0으로 초기화하고 결과에 공백을 추가하였으며, 공백이 아닌 경우 인덱스의 홀짝 여부를 판단해 upper()와 lower() 함수로 결과 문자열을 만들어 나갔다.
def solution(s):
return " ".join(map(lambda x: "".join([a.lower() if i % 2 else a.upper() for i, a in enumerate(x)]), s.split(" ")))
이 문제를 풀며 간과한 점이 있었다. 그것은 바로 split(" ")를 활용하면 공백이 여러 개 붙어 있어도 그 결과를 다시 " ".join()하면 원본과 동일하게 돌아온다는 사실이었다. (테스트해볼 떄 split()으로만 해봤다...) 이 사실을 알았더라면 코드가 훨씬 간결해졌을 텐데.. 아쉬움이 남았다.
이 코드는 split(" ")를 십분 활용하고, map()과 lambda 함수를 잘 활용했다. map()에 인자로 사용한 함수만 따로 확인해 보자.
lambda x: "".join([a.lower() if i % 2 else a.upper() for i, a in enumerate(x)])
이때 입력받는 원소 x는 를 " "으로 split()한 결과이다. 따라서, 각 단어 혹은 공백이라고 볼 수 있는 것이다. 이때 x를 enumerate()로 인덱스 i와 각 문자 a를 순회하며, i의 홀짝 여부에 따라 대, 소문자로 만들어 list에 저장하고 그 결과를 ""로 join한다. 즉, 문제의 의도에 맞게 각 단어별로 대소문자를 설정한 결과를 낼 수 있는 것이다.
split() 함수를 보다 활용하지 못한 점이 아쉬움으로 남는다. 앞으로는 섣불리 판단하지 말고 더 실험해보고 생각해볼 필요가 있겠다..!