Unpacking
a, b = map(int, input().split())
백준 문제를 풀다보면 친숙한 코드입니다. 이것은 iterable (모든 반복 가능한 객체를 iterable 하다고 합니다! 리스트, 튜플, 문자열 등등...) 한 데이터엔 모두 가능한 문법입니다.
입력 받은 list에서 첫번째, 마지막 값 or 나머지 값을 갖고 싶을 때!
_list = [1, 2, 3, 4, 5]
first_index, *rest, last_index = _list
print(rest) # 2 3 4
list 모든 요소 꺼내보기
_list = [1, 2, 3, 4, 5]
for num in _list:
print(num, end = ' ') # 1 2 3 4 5
_list = [1, 2, 3, 4, 5]
print(*_list) # 1 2 3 4 5
list을 튜플로 묶기 , Packing
a, b, c = [1, 2, 3]
d = a, b, c
print(d) # (1, 2, 3)
List Comprehension
_list = [i for i in range(10)] # 0 1 2 3 4 5 6 7 8 9
## 백준 온라인 저지 1920번 "수 찾기" (http://boj.kr/1920)
import sys
input = sys.stdin.readline
_ = input()
_set = set(map(int, input().split()))
q = input()
_list = list(map(int, input().split()))
print(*[1 if dt in _set else 0 for dt in _list], sep = '\n')
(변수를 활용해 만들 값) for (변수 명) in (순회할 수 있는 값)
square = [[x ** 2 for x in range(3)] for _ in range(3)]
print(square) # [[1, 4, 9], [1, 4, 9], [1, 4, 9]]
아래 코드는 너무 투머치해서, 가독성도 해치고 본인도 "내가 뭘 하고 있지?" 할 수 있는 상황...
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print([[x for x in row if x % 3 == 0] for row in matrix if sum(row) >= 10]) # [[6], [9]]
추가적인 예제
# 1 ~ 10을 담는 리스트를 만들어봅시다.
_list = [i for i in range(1,11)]
# 2, 4, 6, ..., 20을 담는 리스트를 만들어봅시다.
_list = [2 * i for i in range(1,11)]
# 주어진 리스트를 받아 3의 배수만 담는 리스트를 만들어봅시다.
tmp = [random.randrange(1, 200) for i in range(100)]
_list = [i for i in tmp if i % 3 == 0]
# 값이 두개 들어있는 튜플을 받아 리스트를 생성하되, 튜플 내부의 값을 뒤집어서 저장하세요.
list_of_tupel = [(i, j) for i in range(100), for j in range(100, 0, -1)]
_list = [(j, i) for i, j in list_of_tuple]
# 주어진 리스트를 그대로 담되, 15가 넘어가는 값은 15로 바꿔서 저장합시다.
_list = [i if i <= 15 else 15 for i in tmp]
# 두 개의 리스트를 합치되, 가능한 모든 조합을 저장하는 리스트를 만들어봅시다.
x = [i for i in range(5)]
y = [i for i in range(5)]
_list = [(i, j) for i in x, for j in y]
자주 헷갈리는 if문의 쓰임새... 앞이냐... 뒤냐...?
앞쪽에 붙는 if는 삼항 연산자의 if라고 생각하면 되고(즉, 값이 앞 조건을 만족하면 어떤 값, 만족하지 못하면 다른 값), 맨 뒤에 붙는 if는 값을 넣을지, 뺄지 결정하는 조건이라고 생각하시면 됩니다!
# 뒤 , 3의 배수만
_list = [i for i in [1,2,3,4,5,6,7,8,9,10] if i % 3 == 0] # 3 6 9
# 앞 , 3의 배수면 그 값, 아니면 15을 출력
_list = [i if i % 3 == 0 for i in [1,2,3,4,5,6,7,8,9,10]] # 15 15 3 15 15 6 15 15 9 15
구체적으로 말씀드리면
if가 뒤에 붙으면 else 을 붙일 수 없고, if가 앞에 붙으면 else 없이 사용이 불가능 합니다.
_list = [i for i in [1,2,3,4,5,6,7,8,9,10] if i % 3 == 0 else 15] # SyntaxError: invalid syntax
_list = [i if i % 3 == 0 for i in [1,2,3,4,5,6,7,8,9,10]] # SyntaxError: invalid syntax
Dictionary 잘 쓰기
값을 찾기 위해 list에서 in을 사용하시나요?
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in range(100):
if i in data:
print(1)
해당 코드는 데이터를 순차적으로 탐색합니다. 그러니까 여기선 하나의 숫자를 찾기 위해 최대 10번 데이터를 확인해야 한다는 이야기겠죠.
뭐 데이터 양이 작다면 모르겠지만, 데이터양이 많으면 많아질수록 엄청나게 시간이 많이 소요됩니다. 당장 리스트에 100,000개의 원소가 있는데 20,000개의 랜덤 데이터가 여기 안에 있는지 찾는다고 생각해보세요.
이럴땐 set을 사용해야 합니다.
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_data_set = set(data)
for i in range(100):
if i in data:
print(1)
실제로 몇 백만개의 데이터가 있는 set에 약 10만 번 정도의 in 연산을 시행해도 1초도 안 걸리는 시간에 완료하는데, list를 사용하게 되면 몇 시간 이상 걸릴 수 있습니다.
또한, set은 중복된 인자를 자동으로 제거해줍니다.
i_want_to_erase_duplicate_element = [21, 31, 65, 21, 58, 94, 13, 31, 58]
completed_list = list(set(i_want_to_erase_duplicate_element)) # 21, 31, 65, 58, 94, 13
test_list = ['Test', 'test', 'TEST', 'tteesstt']
converted_list = list(set(map(lambda string: string.lower(), test_list))) # test, tteesstt
dictionary 생성 방법
fruit = ['apple', 'grape', 'orange', 'banana']
price = [3200, 15200, 9800, 5000]
_dict = {}
for i in range(len(price)):
_dict.append((fruit[i], price[i])) # {'apple' : 3200, 'grape' : 15200, 'orange' : 9000, 'banana' : 5000}
zip을 활용하여 dictionary 생성 방법
fruit = ['apple', 'grape', 'orange', 'banana']
price = [3200, 15200, 9800, 5000]
_dict = dict(zip(fruit, price)) # {'apple' : 3200, 'grape' : 15200, 'orange' : 9000, 'banana' : 5000}
setdefault
fruit = ['apple', 'grape', 'orange', 'banana']
price = [3200, 15200, 9800, 5000]
_dict = dict(zip(fruit, price))
print(_dict['strawberry']) # Error!
print(_dict.setdefault('strawberry', 0)) # 0
setdefault는 딕셔너리에 값이 있을 땐 해당 값을 리턴하고, 값이 없을 땐 두번째 인자(0)로 넘겨준 값을 추가하고 추가한 값을 리턴합니다.
unpacking
fruit = ['apple', 'grape', 'orange', 'banana']
price = [3200, 15200, 9800, 5000]
_dict = dict(zip(fruit, price))
print(*_dict.keys()) # apple grape orange banana
print(*_dict.values()) # 3200 15200 9800 5000
print(*_dict.items()) # ('apple', 3200) ('grape', 15200) ('orange', 9800) ('banana', 5000)
Sorting
sort() ...? sorted()...?
sort()는 리스트를 내부 정렬하는 메소드이고, sorted()는 컨테이너형 데이터를 받아 정렬된 리스트를 돌려주는 함수입니다
_list = [5, 6, 4, 8, 2, 3]
sorted_list = sorted(_list) # 2, 3, 4, 5, 6, 8
_list.sort()
print(_list) # 2, 3, 4, 5, 6, 8
_set = {65, 12, 15, 156, 31, 54, 94, 82, 31} # type : set
_set.sort() # Error!!!!
print(sorted(_set)) # 12, 15, 31, 54, 65, 82, 94, 156
내림차순
_list = [5, 6, 4, 8, 2, 3]
sorted_list = sorted(_list, reversed = True) # 8, 6, 5, 4, 3, 2
두 개의 값을 갖는 튜플을 모은 리스트에서 두 번째 값으로 정렬하고 싶을 때!
_list = [(1, 3), (8, 2), (2, 5), (4, 7)]
sorted_list = sorted(_list, key = lambda dt: dt[1]) # (8, 2), (1, 3), (2, 5), (4, 7)
lambda가 뭐죠? 우선 key는 함수를 입력 받습니다. 즉, lambda가 함수라는 것을 알 수 있습니다.
정확히 말해서, lambda는 익명 함수라는 것으로, 함수의 이름을 명시하지 않고 일회성으로 사용하기 위해 정의하는 것입니다. 여기서 dt는 함수에서 사용할 변수명으로, dt는 각각의 튜플을 저런식으로 사용하겠다는 겁니다.
두 개의 값을 갖는 튜플을 모은 리스트에서
첫번째 값으로 오름차순을 정렬하는데 값이 같으면 두번째 값으로 내림차순 정렬하고 싶을 때!
_list = [(1, 3), (8, 2), (2, 5), (4, 7)]
sorted_list = sorted(_list, key = lambda dt: (dt[1], -dt[0])) # (8, 2), (1, 3), (2, 5), (4, 7)
조건이 여러개인 경우 다음과 같이 튜플 형태로 묶어주는데, 음수가 되면 내림차순으로 정렬한다고 생각하면 됩니다.
Combination/Permutation
import itertools
_list = [1, 2, 3, 4]
iter = itertools.combinations(_list, 2) # 12 13 14 23 24 34
iter = itertools.permutations(_list, 2) # 12 13 14 21 23 24 31 32 34 41 42 43
iter = itertools.combinations_with_replacement(_list, 2) # 11 12 13 14 22 23 24 33 34 44
iter = itertools.product(_list, repeat=2) # 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44
가끔 모든 경우를 탐색해야 하는 상황이 있습니다.
1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열을 모두 구하시오.
일반적으로 백트래킹을 활용해서 문제를 풉니다. 그렇지만, 위 기능을 공부하면 굳이 백트래킹을 할 필요가 없습니다.
combination은 모든 조합을 출력합니다. 즉, 중복이 없고, 순서를 구분하지 않습니다.
permutation은 순열입니다. 중복은 없지만, 순서를 구분합니다
combination_with_replacement는 중복이 가능한 조합입니다. 그래서 combination과 구분하여 11, 22, 33, 44가 새로 들어오죠.
product는 모든 가능한 경우의 수를 출력합니다.
combination을 활용하면 다음과 같은 문제도 해결할 수 있습니다.
전체 리스트에서 3개를 추출하여 곱했을 때, 그 곱의 최댓값을 출력하는 프로그램을 작성하시오.
for, while문 에서의 else
for i in range(N):
for j in range(N):
if sample[i][j] != 1:
break
else:
# Some Code...
어? 굉장히 낯선 코드입니다. for와 while 구문을 진행하다가 else가 나오면, 반복문을 break로 탈출하지 않았다면 진입하는 구간으로 의미가 변경됩니다.
다만, 코드를 줄이는덴 좋긴 하지만, 상황에 따라 본인도 코드를 헷갈려 할 수 있습니다.
이걸 사용하기 전엔 한 번 생각해보고 (익숙해지고 싶다면 주석을 쓰셔도 되겠네요.) 사용해보는걸 권장합니다.
Enumerate
_list = [a, b, c, d, e, f, g]
for idx, val in enumerate(_list):
print(idx, val)
enumerate라는 단어는 열거하다 라는 의미를 갖고 있습니다. enumerate를 사용하면 (인덱스, 값) 의 형태의 튜플을 돌려줍니다. 즉, 힘들게 range()를 사용하지 않아도 되는거죠!
Counter
가끔, 문자열에 들어간 글자를 셀 필요가 있습니다. 일반적으로는 딕셔너리를 사용해서 해결하곤 하죠.
def countLetters(word):
counter = {}
for letter in word:
counter.setdefault(letter, 0)
counter[letter] += 1
return counter
countLetters('Hello World') # {'H': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'W': 1, 'r': 1, 'd': 1}
from collections import Counter
Counter('hello world') # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
from collections import Counter
Counter('hello world').most_common() # [('l', 3), ('o', 2), ('h', 1), ('e', 1), (' ', 1), ('w', 1), ('r', 1), ('d', 1)]
Counter('hello world').most_common(2) # [('l', 3), ('o', 2)]
most_common()을 사용하면 전체 결과를 튜플의 리스트로 리턴하고, 숫자를 명시하면 상위 n개에 해당하는 결과만 출력합니다.
출처
'알고리즘&문제' 카테고리의 다른 글
[알고리즘] 입력 속도 비교 ( Python3, Pypy3) - input() vs sys.stdin.readline() (0) | 2022.08.18 |
---|---|
[알고리즘] 자료구조 시각화 사이트 (0) | 2022.04.23 |
[백준] 백준 문제 풀기 환경 설정 & replit 사용 (0) | 2022.04.10 |
[알고리즘] 자료구조란 (0) | 2022.04.08 |