[T.I.L] 221130 - 리트코드 937, 819번 문제

권병석·2022년 11월 30일
0

T.I.L (스파르타)

목록 보기
12/22
post-thumbnail

#937. 로그 파일 재정렬

로그를 재정렬하라. 기준은 다음과 같다.

1. 로그의 가장 앞 부분은 식별자다.
2. 문자로 구성된 로그가 숫자 로그보다 앞에 온다.
3. 식별자는 순서에 영향을 끼치지 않지만, 문자가 동일할 경우 식별자 순으로 한다.
4. 숫자 로그는 입력 순서대로 한다.

입력

logs = ["dig1 8 1 8 1", "let1 art can", "dig2 3 6",
"let2 own kit dig", "let3 art zero"]

출력

['let1 art can', 'let3 art zero', 'let2 own kit dig', 'dig1 8 1 8 1', 'dig2 3 6']

코드

logs = ["dig1 8 1 8 1", "let1 art can", "dig2 3 6",
        "let2 own kit dig", "let3 art zero"]


def reorderLogFiles(logs_input):
    letters, digits = [], []
    for log in logs_input:
        if log.split()[1].isdigit():
            digits.append(log)
        else:
            letters.append(log)

    print(letters)
    print(digits)

    letters.sort(key=lambda x: (x.split()[1:], x.split()[0]))
    return letters + digits


result = reorderLogFiles(logs)
print(result)

해설

식별자는 순서에 영향이 없으니, 문자와 숫자를 구별해야 한다.
digits와 letters를 빈 배열로 만들어두고
for문을 돌려서
식별자 다음에 오는것이 숫자면 digits에 추가하고
문자면 letters에 추가한다.

여기서 바로 return letters + digits 을 하게 되면
요구 조건 1,2,4는 해결했지만 3은 해결 못한다.

3을 해결하기 위해선 문자를 오름차순으로 정렬을 해야하는데
sort()를 쓴다.
하지만 막 sort()를 써버리면 식별자도 정렬이 되어버려서 기본값으론 못쓴다.
우리가 원하는대로 사용하려면
sort()의 key 값을 바꿔야한다.
식별자는 순서에 영향을 끼치면 안되니까 여기서 lambda식을 쓴다.

현재 digits와 letters에는 이렇게 담겨있을것이다.

letters = ['let1 art can', 'let2 own kit dig', 'let3 art zero']
digits = ['dig1 8 1 8 1', 'dig2 3 6']

숫자 로그는 입력 순서대로 하니까 상관이 없고
letters에서 우리가 원하는 방식으로 정렬을 시키려면
첫번째로 letters[1] 부터 뒤에 있는 문자열들을 확인해서 sort할거고
두번째로 문자가 동일할 경우 식별자 순으로 정렬을 해야하니
다음과 같이 작성한다.

letters.sort(key=lambda x: (x.split()[1:], x.split()[0]))

#819. 가장 흔한 단어

금지된 단어를 제외한 가장 흔하게 등장하는 단어를 출력하라. 대소문자 구분을 하지 않으며, 구두점(마침표,쉼표 등) 또한 무시한다.

입력

paragraph = "Bob hit a ball, the hit BALL flewfar after it was hit."
banned = ["hit"]

출력

"ball"

코드

import collections
import re


paragraph = "Bob hit a ball, the hit BALL flewfar after it was hit."
banned = ["hit"]


def mostCommonWord(srt, banned):
    words = [word for word in re.sub('[^\w]', ' ', srt)
             .lower().split()
             if word not in banned]

    print(words)

    counts = collections.Counter(words)
    print(counts)
    return counts.most_common(1)[0][0]


result = mostCommonWord(paragraph, banned)
print(result)

list comprehension을 알고 있어야 이 코드를 해석할 수 있다.
리스트 컴프리헨션은 쉽게 말해 ‘리스트를 쉽게, 짧게 한 줄로 만들 수 있는 파이썬의 문법’이다.
리스트 컴프리헨션의 기본적인 문법은 다음과 같다.

[ ( 변수를 활용한 값 ) for ( 사용할 변수 이름 ) in ( 순회할 수 있는 값 ) 조건문]

리스트 컴프리헨션의 코드를 해석해보자면
변수 이름을 word로 설정하고
순회할 수 있는 값인 srt를 re.sub(~~~).lower().split()으로 조작, 소문자화 시키고, 나누고, banned가 아닌것만 사용하고
이를 활용한 값을 word에 저장하고 그 word들을 words에 넣어주는 거다.

참고로
re.sub은 문자열을 조작할수 있다.
re.sub('[^\w]', ' ', paragraph) 의 의미는
[^\w] = 문자(\w)가 아닌(^) 것들을 공백(' ')으로 바꿔준다. 라는 의미다.

코드를 보면 중간에 words를 print하는데 그 값은

['bob', 'a', 'ball', 'the', 'ball', 'flewfar', 'after', 'it', 'was']

이렇게 나온다.

자 이제 여기서 가장 많이 나온 단어만 찾아주면 끝나는데
collections.Counter(words)를 하게되면 words에 있는 요소들을 자동으로 카운팅 해줘서 나열해준다.
다음과 같이

Counter({'ball': 2, 'bob': 1, 'a': 1, 'the': 1, 'flewfar': 1, 'after': 1, 'it': 1, 'was': 1})

우리는 counts 에다가 콜렉션.카운터를 저장했으니
counts에서 최빈값(가장 많이 나온 값) 한개를 리턴해주면 된다..!

그러기 위해선

counts.most_common(1)[0][0]

이걸 쓰면 된다.
counts.most_common(1)을 하게되면 [('ball', 2)]
counts.most_common(1)[0]을 하게되면 ('ball', 2)
counts.most_common(1)[0][0]을 하게되면 ball 만 나온다

두 문제 핵심 요약

sort(key=lambda) , re.sub, collections.Counter(), .most_common 등등

profile
Back-End 개발자를 꿈꾸는 디제이였던 백수의 TIL 일기장 입니다.

0개의 댓글