파이썬 enumerate, zip, 딕셔너리, Counter 객체

이은지·2022년 6월 6일
1

코딩 테스트

목록 보기
2/10

https://programmers.co.kr/learn/courses/30/parts/12077
프로그래머스 코테 고득점 kit 풀어보는 중. 오늘은 그 중 '해시' 파트 4문제를 풀었당.
6월 12일날 코테 보고 싶어서 결국 익숙한 파이썬으로 빽 했다.

해시가 무슨 문제 유형인가 했는데
파이썬에서 해시 유형은 dictionary 자료구조를 얼마나 잘 쓸 수 있냐를 묻는 것 같다.

enumerate

enumerate란?

iterable한 자료형을 인자로 넣으면 (인덱스,값) 형태의 enumerate 객체를 반환한다.
for문과 사용할 수도 있고, 리스트나 딕셔너리 형태로 만들 수도 있다.

헷갈리지 말고 기억하자. 인덱스가 먼저고 값이 그 다음인 형태다.

파이썬이 권장하지 않는 for문 사용 방식

for i in range(len(arr)):
	print(arr[i])

파이썬이 권장하는 방식

for item in arr:
	print(item)

위 두 가지 방식의 차이를 이해했다면 enumerate의 쓰임이 어디에 있는지도 대강 감이 올 것이다.
for문 사용 시 현재 몇 번째 반복문인지(for문의 i)를 알아야 할 때가 많다. 이때 이 목적을 위해 for i in range(len(arr))를 사용하는 게 아니라, enumerate를 활용하는 것이다.

eumerate를 사용한 for문

arr = ['a','ab','abc']
for idx,val in enumerate(arr):
	print(idx,val)
    
# result
0 a
1 ab
2 abc

enumerate 객체들을 담은 리스트나 딕셔너리를 만들 수도 있다.

zip

여러 개의 iterable한 객체를 인자로 받아 인덱스별로 값을 zip해준다.
한 엔트리에 대한 정보가 여러 개의 배열에 나눠 담겨져 있을 때 사용하면 좋을 듯하다.

numbers = [1,2,3]
letters = ['a','ab','abc']

# zip 사용
for pair in zip(numbers,letters):
	print(pair)

# zip 사용 X
for i in range(i):
	print(numbers[i], letters[i])

for문을 돌 때 배열에 인덱스로 접근하는 걸 지양해야겠다.

문자열에서도 사용 가능하고, zip한 결과를 딕셔너리에 담을 수도 있다.

# 문자열 사용 예시
str1 = "abc"
str2 = "123"
str3 = "ABC"
for first,second,third in zip(str1,str2,str3):
	print(first,second,third)
# result
a 1 A
b 2 B
c 3 C
# 딕셔너리 변환
numbers = [1,2,3]
letters = ['a','ab','abc']

dic = dict(zip(letters,numbers))

참고로 인자로 넘겨준 iterable 객체의 길이가 서로 다르면 길이가 짧은 객체 길이에 맞춰 pair가 생성된다.
나머지는 버려진다.

딕셔너리

특정 값을 검색해야 하는 문제에서 쓰면 유용하다.
인덱스가 아니라 '특정 값'을 찾아야 하는 경우 리스트는 O(N)의 시간이 걸린다. 우리가 가지고 있는 정보가 인덱스 밖에 없기 때문에 인덱스로 모든 배열을 순회해야 한다.
반면 딕셔너리는 값을 알고 있으면 O(1)으로 해당 값에 접근할 수 있다.

딕셔너리 컴프리헨션

  • 인덱스와 값으로 딕셔너리 만들기 - enumerate
names = ['James', 'Judy', 'Jin']
dic = {v:i for i,v in enumerate(names)}
# {'James':0, 'Judy':1, 'Jin':2}
  • 두 가지 값으로 딕셔너리 만들기 - zip
names = ['James', 'Judy', 'Jin']
height = [180, 160, 170]
dic = {name:height for name,height in zip(names,height)}
# {'James': 180, 'Judy': 160, 'Jin': 170}
  • 특정 조건을 만족할 때에만 딕셔너리에 추가하기
    ex 키가 170 이상인 사람만 딕셔너리에 추가
dic = {name:height for name,height in zip(names,height) if height>=170}
# {'James': 180, 'Jin': 170}

값 검색하기

두 가지 방식이 있다.
1. dic[val]
2. dic.get(val)

딕셔너리에 없는 값에 접근했을 때 1번 방법은 오류를 내고 코드를 종료시킨다.
2번 방법은 None을 리턴한다. 따라서 값의 유무를 검색해야 할 때는 1번 방법이 아닌 2번 방법을 사용해야 한다.

가령 아래와 같은 패턴이다. None은 꼭 대문자로 시작해야 함에 유의!
반대는 is not None 이다.

names = ['James', 'Judy', 'Jin']

for name in names:
	if dic.get(name) is None:
    	# 존재하지 않는 key값에 대한 처리
    elif dic.get(name) is not None:
    	# 존재하는 key값에 대한 처리

# in, not in 을 활용해도 값 유무에 따른 분기를 해줄 수 있다.
for name in names:
	if name in dic:
    	# 존재하지 않는 key값에 대한 처리
    elif name not in dic:
    	# 존재하는 key값에 대한 처리

혹은 자바스크립트의 || 처럼 딕셔너리에 key가 존재할 때는 상응하는 value값을, 존재하지 않으면 내가 설정한 기본값을 리턴하도록 할 수도 있다.

dic = {'James': 180, 'Judy': 160, 'Jin': 170}
users = ['June','James','Judy','Jack']
for user in names:
	print(dic.get(name,0))
# result
...
0
180
160
0

아래 두 가지 코드는 같은 결과값을 갖는다.

>>> for user in users:
...     if user in dic:
...             print(dic.get(user))
...     elif user not in dic:
...             print("No information")

>>> for user in users:
...     print(dic.get(user,"No information"))

...
No information
180
160
No information

순회하기

  • key만 순회하기
  • key,val 함께 순회하기

key와 value를 함께 순회할 때는 딕셔너리 뒤에 .items()를 붙여줘야 된다. 안그럼 오류 남.

>>> for key in dic:
...     print(key)
...
James
Judy
Jin
>>> for key,val in dic.items():
...     print(key,val)
...
James 180
Judy 160
Jin 170

정렬하기

  • key 값으로 정렬
  • value 값으로 정렬

이 내용은 오늘 정렬 문제 풀고 다른 글로 정리하겠당.

Counter 객체

Collections 모듈에 속한 클래스다.
데이터 별로 개수를 셀 때 사용한다.
프로그래머스 해시 문제 푸는데 Counter 사용한 풀이 보고 정말 혁신적이라고 느꼈당...

>>> from collections import Counter
>>> str = 'hello world'
>>> print(Counter(str))
Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
>>> print(Counter(str).most_common(2))
[('l', 3), ('o', 2)]

>>> arr = ['Kim', 'Kim', 'Lee', 'Kim', 'Park', 'Kown', 'Lee']
>>> print(Counter(arr))
Counter({'Kim': 3, 'Lee': 2, 'Park': 1, 'Kown': 1})

문자열에서 알파벳 개수 셀 때 유용할듯. 파이썬 없이 억덕게 살아~~
Counter 객체끼리 뺄셈도 가능하다.

profile
교육학과 출신 서타터업 프론트 개발자 👩🏻‍🏫

1개의 댓글

comment-user-thumbnail
2024년 1월 15일

포스팅 너무 잘 읽었습니당 :)

답글 달기