프로그래밍/Python

[Python] 함수 사용법 - (1) enumerate()

Churnobyl 2023. 2. 28. 21:47
728x90
반응형

 

프로그래머스 코딩테스트를 풀다가 아름다운 코드를 하나 보았다

문제를 풀고 다음 문제로 넘어가기 전에 다른 사람이 푼 코드를 보았는데 너무 깔끔해서 마음에 들었다

'가장 아름다운 하나의 답이 존재한다'는 파이썬의 슬로건에 맞는 코드였다

거기에 사용된 함수를 하나씩 설명하면서 내 실력도 올려보려고 한다

def solution(array):
    while len(array) != 0:
        for i, a in enumerate(set(array)):
            array.remove(a)
        if i == 0: return a
    return -1

solution([1, 2, 3, 3, 3, 4])

위 문제는 주어진 array에서 최빈값을 구하는 문제였다

 

 


enumerate(iterable, [start=0])

iterable한 객체를 열거해서 enumerate 객체를 리턴한다

 

  • iterable: member를 하나씩 차례로 반환 가능한 객체
  • Optional Parameter
    • start : 카운트를 시작할 숫자. 기본값 0

아래의 예제를 보자

 

shopping_basket = ['감자', '딸기', '양지머리', '김치']

# 1
print(enumerate(shopping_basket))  

# 2
print(list(enumerate(shopping_basket)))  

# 3
print(list(enumerate(shopping_basket, start=1)))

# 4
print(dict(enumerate(shopping_basket)))
<enumerate object at 0x0000025D834716C0>
[(0, '감자'), (1, '딸기'), (2, '양지머리'), (3, '김치')]
[(1, '감자'), (2, '딸기'), (3, '양지머리'), (4, '김치')]
{0: '감자', 1: '딸기', 2: '양지머리', 3: '김치'}

 

# 1

enumerate()함수는 enumerate object를 리턴하므로 위와 같은 함수의 실제 주소가 출력됐다

 

# 2

shopping_basket list의 인덱스(index)요소(element)로 이루어진 튜플(tuple) 리스트가 리턴됐다

 

# 3

옵셔널 파라미터 start=1로 해주었을 때 시작하는 인덱스(index)가 1이 되었다

 

# 4

enumerate object를 dict()함수로 감싸주었을 때는 튜플의 요소가 각각 keyvalue로 출력되었다

 

 


사용법

enumerate()함수는 주로 for문과 함께 사용된다.

iterable한 객체를 index값으로 순서를 매겨 사용하려고 만드는 경우가 대부분이기 때문이다

 


아래의 예제를 보자

shopping_basket = ['감자', '딸기', '양지머리', '김치']

# 1
for i in range(len(shopping_basket)):
    print(i, shopping_basket[i])
    
# 2
for i, item in enumerate(shopping_basket):
    print(i, item)

예제 #1과 #2는 정확히 똑같은 결과를 리턴한다

0 감자
1 딸기
2 양지머리
3 김치
0 감자
1 딸기
2 양지머리
3 김치

 

# 1

len()함수로 shopping_basket list의 길이를 리턴하고 range()함수로 0부터 len(shopping_basket) - 1까지 i를 for문으로 반복한다

 

# 2

enumerate()함수로 튜플 객체를 i와 item에 하나씩 리턴시켜 반복한다

 

 

 


코드풀이

이제 코드를 하나씩 뜯어보자

전체코드

def solution(array):
    while len(array) != 0:  # 3
        for i, a in enumerate(set(array)):  # 1
            array.remove(a)
        if i == 0: return a  # 2
    return -1  # 4

solution([1, 2, 3, 3, 3, 4])

 

#1

for i, a in enumerate(set(array)):
            array.remove(a)

for문부터 보자

set()함수로 array의 unique한 값만을 취한 뒤에 enumerate()함수로 (0, x1), (1, x2), ... 형태의 enumerate객체로 만들었다

for문의 결과는 다음과 같다

(0, 1)
(1, 2)
(2, 3)
(3, 4)

그리고 for문이 돌 때마다 array.remove(a)로 a값을 하나씩 지워준다

그렇게 되면 [1, 2, 3, 3, 3, 4]에서 [1, 2, 3, 4]가 하나씩 지워질 것이다

array = [3, 3]

 

#2

if i == 0: return a

이제 컴퓨터는 if문을 거친다

i == 0이면 a를 리턴하라

for문이 다 돌고 나서 i값에는 for문의 가장 마지막 값이 남아 있을 것이다.

즉 위의 for문이 돌고 난 후에 i에는 3이란 값이 남아 있으니 if문의 조건은 False이며 다시 while문으로 올라간다

 

#3

while len(array) != 0:

len(array) != 0. 즉, array의 길이가 0이 아니면 계속 while문이 돈다

#1번에서 array에는 [3, 3]이 남아있었으니 한번 더 while문이 돌게 된다

 

다시한번 for문으로 들어가 enumerate(set(array))는 (0, 3)이라는 유일한 enumerate객체를 생성하고 array에서 3을 하나 지운 뒤 다시 if문에서 조건을 검사한다

 

이제 i에는 0이라는 값이 저장되어 있으므로 if문의 조건을 충족한다

 

따라서 a = 3인 3을 리턴해 최빈값을 찾을 수 있다

 

 

#4

return -1

문제의 조건에서 최빈값이 없을 경우 -1을 리턴하라고 했다

array가 [1, 1, 2, 2, 3, 3, 4]인 경우를 생각해보자

#1에서 [1, 2, 3, 4]인 값이 제거되고 array에는 [1, 2, 3]이 남을 것이다

또한 i = 3이므로 while문이 한번 더 돌고 다시 한번 #1에서 unique한 값인 [1, 2, 3]이 array에서 제거되므로 array에는 아무 것도 남지 않게 된다

결국 while문의 조건에 따라 while문을 빠져나가게 되고 -1을 리턴한다

 

 

 

 


생각

간단하지만 enumerate()함수의 특성을 잘 활용해서 푼 정답이라고 생각한다

반응형