금지된 단어를 제외한 가장 흔하게 등장하는 단어를 출력하라. 대소문자 구분을 하지 않으며, 구두점(마침표, 쉼표)또한 무시한다.
입력
paragraph = "Bob hit a ball, the hit BALL flew far after it was hit."
출력
"ball"
code: most_common.py
이 문제를 푸는 방법은 다양하지만, 파이썬의 장점을 살릴 수 있는 풀이를 알아보자.
먼저, 데이터의 전처리 과정에서 대소문자의 구분과 구두점을 없애기 위해 정규식을 사용할 수 있다.
[word for word in re.sub(r'[^\w]', ' ', paragraph)
.lower().split()
if word not in banned]
정규식에서 ^는 not, \w는 word를 뜻한다. 따라서, sub 메소드를 통하여 정규식에 해당되는 word가 아닌 paragraph의 문자는 공백으로 치환된다.
그 후, 해당 paragraph는 lower 된 다음 split된다.
split 된 결과물은 전처리된 paragraph 문자열이 공백을 기준으로 나뉜 word의 list가 될것이다.
해당 list를 for in 문을 통해 각각의 단어에 대해 not in banned인지 검사 하고, 통과된다면, 최종적으로 []안에 삽입된다.
해당 구문에 대한 가독성이 뛰어나다고 할 수는 없지만, 천천히 뜯어보면 이해하기 어렵지 않고, 작성하기도 쉬운 코드이다.
개수를 처리하는 부분은 두 가지 방법이 있다.
첫번째는 dict를 활용하는 방법인데, collections.defaultdict(int)를 통해 개수를 담는 변수가 int 기본값이 자동으로 부여되게 한다.
counts = collections.defaultdict(int)
for word in words:
counts[word] += 1
이렇게 하면, 해당 키가 개수를 count하는 dict에 존재하는지 검사할 필요 없이, 자동으로 0의 기본값이 부여된 것에 +=1 처리를 해줄 수 있다.
그 후, max 메소드를 사용하여 딕셔너리에서 값이 가장 큰 키를 가져온다.
max 메소드는 기본적으로 dictionary의 각 key의 값 중에서 가장 큰(ASCII값)것을 검사하지만, key를 지정하여 각 key값이 어떻게 적용될 지 설정할 수 있다.
여기에서는, key값을 get하여 그 중에서 가장 큰 값이 return 되도록 한다.
return max(counts, key=counts.get)
# 위의 코드는
# max(counts, key=lambda key: counts[key])
# 와 같다.
다음 방법으로, dict에서 개수를 처리하는 부분은 Counter 모듈을 사용할 수 있다.
counter 모듈의 most_common(n) 메소드는 해당 counter 안의 가장 빈도수가 높은 n개를 list안의 tuple 형태로 반환한다.
[('a', 3)]
의 형태이다.
따라서 주어진 문제에서 most_common(1)로 가장 빈도수가 높은 것을 가져오고 [0][0]의 인덱스인 list안의 tuple의 첫 요소를 가져오면 된다.
counts = collections.Counter(words)
return counts.most_common(1)[0][0]
전체 코드는 다음과 같다.
def mostCommon(paragraph, banned):
words = [word for word in re.sub(r'[^\w]', ' ', paragraph)
.lower().split()
if word not in banned]
counts = collections.Counter(words)
print(counts)
return counts.most_common(1)[0][0]