문제
금지된 단어를 제외한 가장 흔하게 등장하는 단어를 출력하라. 대소문자 구분을 하지 않으며, 구두점(마침표, 쉼표 등) 또한 무시한다.
예제1
입력
input: paragraph = "Bob hit a ball, the hit BALL flew far after it was hit."
banned = ["hit"]
출력
output: "ball"
풀이1 리스트 컴프리헨션과 defaultdict 모듈을 사용하기
입력값에는 대소문자가 섞여 있으며 쉼표 등 구두점이 존재한다. 따라서 데이터 클렌징을 이용해 입력값에 대한 전처리 작업이 필요하다.
좀 더 편리하게 처리하기 위해 정규식을 섞어 쓰면 다음과 같이 처리할 수 있다.
words = [word for word in re.sub(r'[^\w]', ' ', paragraph).lower().split() if word not in banned]
위 정규식에서 \w는 단어 문자를 뜻하며, ^은 not을 의미한다. 그대로 직역하면 단어 문자가 아닌 것을 그 뒤의 ' '에서 공백으로 치환하게 되므로 입력으로 들어온 문자열에서 단어 문자로 들어온 것이 아닌 나머지 문자를 모두 공백으로 치환하고, lower( )를 통해 소문자로 변환한 후 다시 split( )로 공백을 기준으로 분리해주게 된다. 이 과정에서 가장 우측에 있는 if문에서 banned 리스트에 속하지 않는 값을 word로 다시 옮겨주게 되니, 결국에는 단어 문자를 제외한 모든 불필요한 문자가 제거되어 words에는 단어만 담기게 된다. 그 이후에는 각 단어의 개수만 헤아려주면 된다.
counts = collections.defaultdict(int) # 기본으로 int 값을 자동으로 부여
for word in words: # 위에서 가져온 단어들의 개수를 세어준다.
counts[word] += 1 # 단어가 1번 등장할 때마다 1씩 증가
위 코드를 통해서 딕셔너리로 값을 생성하는데 기본으로 int 값을 자동으로 부여하게 하였으며, words의 단어 리스트를 가져와 word에 담아주고, counts 딕셔너리의 word(단어)에 해당하는 값에 +1을 해주면 각 단어의 갯수만큼 딕셔너리의 값이 계속해서 증가하게 된다.
return max(counts, key=counts.get)
이후에 counts에서 가장 많이 등장하는 단어를 리턴한다.
전체 코드는 다음과 같다.
# input: paragraph = "Bob hit a ball, the hit BALL flew far after it was hit."
# banned = ["hit"]
# output: "ball"
import collections
import re
def solution(paragraph: str, banned: list[str]) -> str:
words = [word for word in re.sub(r'[^\w]', ' ', paragraph).lower().split() if word not in banned]
# 첫번째 방법 -> defaultdict를 이용해 int 값 자동 부여하기
counts = collections.defaultdict(int) # 기본으로 int 값을 자동으로 부여
for word in words: # 위에서 가져온 단어들의 개수를 세어준다.
counts[word] += 1 # 단어가 1번 등장할 때마다 1씩 증가
return max(counts, key=counts.get)
banned = ["hit"]
print(solution(str(input("단어를 입력: ")), banned))
풀이2 Counter 객체와 most_common 함수를 사용한 풀이
먼저 데이터 클렌징 하는 부분은 위 방법과 동일하지만, 클렌징한 데이터에서 가장 많이 등장하는 단어를 추출하는 방법이 간소화된다.
most_common 함수의 인자로 가장 많이 등장하는 값을 앞에서부터 몇 개 출력할건지 전달하면 그 단어와 개수를 리턴받게 된다.
그 후 개수가 아닌 단어의 인덱스를 뽑아 리턴하면 깔끔하게 요구하는 출력대로 값을 리턴할 수 있다.
전체 코드는 다음과 같다.
# input: paragraph = "Bob hit a ball, the hit BALL flew far after it was hit."
# banned = ["hit"]
# output: "ball"
import collections
import re
def solution(paragraph: str, banned: list[str]) -> str:
words = [word for word in re.sub(r'[^\w]', ' ', paragraph).lower().split() if word not in banned]
# 두번째 방법 -> Counter 객체를 이용해 가장 흔하게 등장하는 단어를 most_common으로 추출
counts = collections.Counter(words)
return counts.most_common(1)[0][0]
banned = ["hit"]
print(solution(str(input("단어를 입력: ")), banned))
이처럼 가장 많이 등장하는 값(최빈값)을 구하는 문제에서는 Counter 객체를 이용하게 되면 비교적 간단히 구현할 수 있게 된다.
알게된 점
리스트 컴프리헨션을 통한 코드 간결화
collections 모듈의 Counter 객체와 most_common( ) 함수를 이용한 최빈값 출력
정규식을 통해 원하는 데이터를 구하기 위한 정규화 방법
공부할 것
리스트 컴프리헨션 구현하기
'알고리즘 문제 풀이' 카테고리의 다른 글
[알고리즘 문제 풀이] 가장 긴 팰린드롬 부분 문자열 (0) | 2022.08.24 |
---|---|
[알고리즘 문제 풀이] 그룹 애너그램 (0) | 2022.08.19 |
[알고리즘 문제 풀이] 로그 파일 재정렬 (0) | 2022.08.12 |
[알고리즘 문제 풀이] 문자열 뒤집기 (0) | 2022.08.12 |
[알고리즘 문제 풀이] 유효한 팰린드롬 (0) | 2022.08.12 |