https://school.programmers.co.kr/learn/courses/30/lessons/17686
주어진 파일명을 규칙에 맞게 정렬하는 문제이다.
숫자를 기준으로 파일명을 head, number, tail로 구분하는데, head는 문자로만 구성되어 있으며 문자열 시작~숫자가 나올 때까지가 head이다. number는 숫자로만 이루어져 있다. 붙어있는 숫자들인 number 이후의 문자열이 tail이다. tail은 숫자, 문자 상관없이 number 이후부터가 모두 tail이다.
다음의 우선순위에 따라 리스트를 정렬해야 한다.
문제 풀이의 핵심 로직은 [1] head/number/tail을 적절히 파싱 후, [2] 단계에 맞춰 정렬 및 출력하는 것이다.
대소문자 구분을 하지 않으므로 lower()
를 써서 비교대상을 소문자로 통일하고, sorted()
와 lambda
를 사용해 단계별 기준을 적용해 정렬하면 된다. 2단계에서 앞에 붙은 0을 무시하려면, 그러니까 001과 01을 같은 1로 취급하려면 int()
를 활용하면 되겠다.
우선 입력으로 주어진 리스트를 숫자를 기점으로 분해하라는 조건에서 파이썬 정규식의 re.split()
을 떠올렸다.
반복문을 돌면서 isdigit()
을 사용, 숫자가 나오면 그 이전까지가 head이다. head와 number를 구분하는 것은 쉬운데, number와 tail을 어떻게 구분할까 고민했다. 처음엔 원래 순서를 기억하는 배열을 만들어 인덱스를 부여하려고 했는데, 파이썬에서 제공하는 sort()
함수는 stable
을 지원하는 함수라는 걸 알게 되어 그냥 head와 number만 고려하면 문제가 해결되었다.
stable sort란?
정렬하기 전과 후의 순서를 보장해주는 sort 방법이다. 예를 들면, [5, 1, 3, 2, 2, 4]를 정렬한다고 했을 때 결과는 당연히 [1, 2, 2, 3, 4, 5]가 될 것이다. 여기서 stable한 sort를 했다면 결과는 [1, 2, 2, 3, 4, 5]가 될 것이다. 볼드 처리한 2가 sort 전/후에도 여전히 뒤의 순서를 유지하는 것이다.
예제
from operator import itemgetter data = [('앞',3), ('x',2), ('뒤',3), ('x',1)] ret = sorted(data, key=itemgetter(1)) # 튜플 뒤의 숫자를 기준으로 정렬 print(ret) # [('x', 1), ('x', 2), ('앞', 3), ('뒤', 3)]
뒤의 숫자를 기준으로 정렬했다.
1,2,3,3
순서로 정렬이 될 것이다. 같은 3값을 가지고 있는('앞',3), ('뒤',3)
는 순서가 그대로 유지된다.
import re
def solution(files):
temp = [re.split(r"([0-9]+)", s) for s in files]
sort = sorted(temp, key = lambda x: (x[0].lower(), int(x[1])))
return [''.join(s) for s in sort]
r prefix
temp = [re.split(r"([0-9]+)", s) for s in files]
이 라인의 re.split()
정규식 앞에 r
이 붙어있는데, 이건 raw를 의미한다. 아래의 예시코드를 보면 직관적으로 이해가 된다.
print("hello\n") # hello와 줄바꿈이 출력
print(r"hello\n") # raw string, \n이 문자열로 취급되어 출력
def solution(files):
temp = []
head, number, tail = '', '', ''
for file in files:
for i in range(len(file)):
# head와 number 구분
if file[i].isdigit():
head = file[:i]
number = file[i:]
for j in range(len(number)):
# number와 tail 구분
if not number[j].isdigit():
tail = number[j:]
number = number[:j]
break
temp.append((head, number, tail))
head, number, tail = '', '', ''
break
temp = sorted(temp, key=lambda x:(x[0].lower(), int(x[1])))
return [''.join(i) for i in temp]