파이썬 중복을 제거하는 set 잘 활용하기

1. 문제

 

https://programmers.co.kr/learn/courses/30/lessons/92334

 

코딩테스트 연습 - 신고 결과 받기

문제 설명 신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다. 각 유저는 한 번에 한 명의

programmers.co.kr

 

신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다.

 

무지가 개발하려는 시스템은 다음과 같습니다.

 

각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.

 

신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.

 

한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.

 

k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.

 

유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.

 

이용자의 id가 담긴 문자열 배열 id_list, 각 이요자가 신고한 이용자의 id 정보가 담긴 문자열 배열 report,

 

정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return하도록 solution 함수를 완성해주세요.

 

2. 제한사항

 

 

3. 예시

 

 

 

4. 나의 풀이

 

잘 모르겠으면 예시 설명에 나온 흐름을 따라 그대로 구현하는게 바람직하다

 

제한사항중에 한 유저를 여러번 신고할 수 있지만 동일한 유저에 대한 신고 횟수는 1회로 처리한다

 

report의 형식을 보면 "이용자id 신고한id" 형태로 되어있고

 

예시 2번째를 보면 "ryan con", "ryan con", "ryan con", "ryan con" 모두 1회 신고한 것으로 취급한다고 했으니까

 

처음부터 report의 중복을 제거하는 방법으로 간다

 

리스트의 중복을 제거하는 방법은 set으로 변환하고 다시 list로 바꾸는 방법이 있다

def solution(id_list, report, k):
    
    answer = []
    
    report = list(set(report))

 

그 다음에 이제 누가 누구를 신고했는지, 누구는 몇번 신고당했는지를 구해야한다

 

신고당한 횟수를 비교해서 누가 정지당했는지 파악하고

 

정지당한 id를 누가 신고했는지 파악해야 누가 메일을 몇통 받았는지 구할 수 있으니까

 

def solution(id_list, report, k):
    
    answer = []
    
    report = list(set(report))
    
    reporter_dict = {id_str:[] for id_str in id_list}
    
    reported_dict = {id_str:0 for id_str in id_list}

 

리스트 뿐만 아니라 dict에서도 위와 같이 comprehension이 가능함

 

다음 report에서 하나씩 돌아서 누가 누구를 신고했는지 파악해서 reporter_dict와 reported_dict를 채운다

 

def solution(id_list, report, k):
    
    answer = []
    
    report = list(set(report))
    
    reporter_dict = {id_str:[] for id_str in id_list}
    
    reported_dict = {id_str:0 for id_str in id_list}
    
    for rep in report:
        
        rep_split = rep.split()
        
        reporter,reported = rep_split[0],rep_split[1]
        
        reporter_dict[reporter].append(reported)
        
        reported_dict[reported] += 1

 

다음으로 reported_dict가 채워졌으니까 이제 누가 정지당했는지를 파악한다

 

reported_dict.items()를 이용해서 key,value를 순회할수 있다

 

def solution(id_list, report, k):
    
    answer = []
    
    report = list(set(report))
    
    reporter_dict = {id_str:[] for id_str in id_list}
    
    reported_dict = {id_str:0 for id_str in id_list}
    
    for rep in report:
        
        rep_split = rep.split()
        
        reporter,reported = rep_split[0],rep_split[1]
        
        reporter_dict[reporter].append(reported)
        
        reported_dict[reported] += 1
        
    stop_list = []
    
    for reported,value in reported_dict.items():
        
        if value >= k:
            
            stop_list.append(reported)

신고당한 횟수가 k이상이면 정지당한 id 리스트에 집어넣어줌

 

다음으로 reporter_dict를 순회해서 정지메일을 발송함

 

def solution(id_list, report, k):
    
    answer = []
    
    report = list(set(report))
    
    reporter_dict = {id_str:[] for id_str in id_list}
    
    reported_dict = {id_str:0 for id_str in id_list}
    
    for rep in report:
        
        rep_split = rep.split()
        
        reporter,reported = rep_split[0],rep_split[1]
        
        reporter_dict[reporter].append(reported)
        
        reported_dict[reported] += 1
        
    stop_list = []
    
    for reported,value in reported_dict.items():
        
        if value >= k:
            
            stop_list.append(reported)
            
    for reporter,rep_list in reporter_dict.items():
        
        stop = 0
        
        for rep in rep_list:
            
            if rep in stop_list:
                
                stop += 1
                
        answer.append(stop)
        
    return answer

 

reporter_dict는 이용자id : [ 신고한 id 리스트 ]형태이고 stop은 정지메일 받은 횟수

 

rep_list인 신고한 id 리스트를 순회해서 각 id가 정지당한 id리스트인 stop_list에 존재하면

 

정지메일을 받았으니 stop에 1을 더해줘

 

처음에 dict comprehension할때 id_list에서 순서대로 reporter_dict에 집어넣었으니까

 

그냥 answer에 바로 stop을 append하면 된다

 

 

5. 다른 풀이

 

좋아요를 가장 많이 받은 풀이에 대해 보면 나랑 비슷함

 

def solution(id_list, report, k):
    
    answer = [0] * len(id_list)    
    
    reports = {x : 0 for x in id_list}

    for r in set(report):
        
        reports[r.split()[1]] += 1

    for r in set(report):
        
        if reports[r.split()[1]] >= k:
            
            answer[id_list.index(r.split()[0])] += 1

    return answer

 

answer = [0] * len(id_list)를 해서 id_list 길이만큼 [0,0,0,0,...]으로 채워넣어

 

reports = {x : 0 for x in id_list}는 이용자id와 신고당한 횟수를 사전으로 만든거네

 

나랑 다른 점은 신고한 id리스트를 value로 가지는 사전 reporter_dict는 안만들었네

 

그래도 가능하다고??

 

다음 set(report)에서 report의 중복을 제거한 set에서 하나씩 순회한다음에

 

r.split()[1]은 신고당한 id를 나타내고 reports에 key로 넣고 1씩 더해주면 각 id가 몇번 신고당했는지 reports가 완성

 

다음 set(report)에서 또 하나씩 순회하는데

 

reports[r.split()[1]]은 신고당한 id가 몇번 신고당했는지 구해주고 이게 k 이상이면 이 id는 정지당한 id라는것

 

그렇다면 그 id를 신고한 이용자 id에 대해서 정지메일을 보낼건데 그 id를 신고한 이용자 id는 어떻게 찾냐??

 

r.split()[0]은 그 정지당한 id를 신고한 id이고 id_list.index()에 집어넣으면 그 정지당한 id를 신고한 id가 

 

id_list에서 어디 index에 존재하는지 index를 반환하고

 

그러면 그 index는 정지메일을 한번 받은거니까 answer의 그 index 값을 1 더해주면 된다

 

이래서 처음에 answer = [0] * len(id_list)로 초기화했네

 

 

6. 되돌아보기

 

예시에서 설명해준 흐름에 따라 구현을 잘 했다

 

중복을 제거하는 set을 잘 활용했다

 

dict comprehension도 가능하다는 점 기억하면 좋다

 

TAGS.

Comments