[Python] 코테에서 자주쓰이는 함수 총정리

신선한양배추·2023년 10월 18일
0
post-thumbnail

알고리즘 문제에서 자주 쓰이는 함수들을 모아서 정리해봤습니다.
실전에서 많이 쓰이는 함수만 모으고 나머지는 과감히 삭제했습니다.
주기적으로 업데이트 해나갈 예정입니다.

최근수정일: 2023-10-28

Pythonic code

참고: https://github.com/VSFe/Algorithm_Study/blob/main/Concept/Prev/vol.2/00_Special/Pythonic_Code_For_Coding_Test.md

unpacking

lst = [1,2,3,4,5]
first_index, *rest, last_index = lst  # rest=[2,3,4]

print(*lst)  # 1 2 3 4 5

a, b, c = [1, 2, 3]
d = a, b, c  # d = (1, 2, 3)

List Comprehension

(변수를 활용해 만들 값) for (변수 명) in (순회할 수 있는 값)

if의 쓰임새:
앞쪽에 붙는 if는 삼항연산자의 if 이다. 즉 {참일때값} if {조건} else {거짓일때 값}
뒤쪽에 붙는 if는 값을 넣을지 뺄지 결정하는 조건이다.


[i for i in tmp if i % 3 == 0] # tmp에서 3의 배수만 넣기
[(j, i) for i, j in list_of_tuple] # 튜플을 뒤집기
[i if i <= 15 else 15 for i in tmp] # 15가 넘어가는값은 15로 바꾸기
[(i, j) for i in x, for j in y] # x,y에서 하나씩 뽑아서 가능한 모든 조합을 저장하기

{b:c for b, c in zip(['a', 'b', 'c'], [1,2,3]) }  # 딕셔너리도 가능

# 이중 list comprehension (비권장)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row] 
# flat == [1, 2, 3, 4, 5, 6, 7, 8, 9]

for, while 문에서의 else

for j in range(N):
	if sample[i][j] != 1:
		break
else:
	# 반복문을 break로 탈출하지 않으면 진입하는 구간

최대값 찾기

참고: https://ooyoung.tistory.com/75

max({iterable}, [,default,key]) 
	# "1" < "a" < "ㄱ"
	# 'AAB' > 'AAAB'
	# default: iterable 객체가 비어있을경우 반환할 값. 없으면 비어있을때 에러남
min(-5, 3, 0, 3, -5, key=abs)  # 절댓값이 가장 작은 값
max(*a,*b,*c)  # a,b,c 배열에서 가장 큰 원소
	

문자열

단어의 개수, 인덱스 찾기

s.count(찾을 값) # 문자열 내에서 찾을 값의 개수 반환
s.find(찾을값, 시작, 종료) # 값이 처음으로 나타나는 위치 반환.
						# 값이 없을경우 -1 반환.
s.rfind(찾을값, 시작, 종료) # 반대로 찾기

나누고 합치기

s.split({delim})
	# split()과 split(' ')는 다르다. split()은 공백이 연속되여도 하나로봄.
s.splitlines() # \n 기준으로 나눔
{delim}.join(lst_or_set)

대소문자 바꾸기

s.upper()
s.lower()
s.isupper() # 문자열 전체가 대문자인지 판정함
s.islower() # 문자열 잔체가 소문자인지 판정함
s.swapcase() # 대소문자 반대로 만들어 리턴
s.title() # 각 단어의 앞글자만 대문자로 바꾸어 리턴. 
	# 단어를 나누는 기준은 '문자가 아닌 모든 글자'임
	#'3people' -> '3People'
string.capwords(str, ' ') # 각 단어를 공백으로 나눈다음 앞글자를 대문자로 바꿔서 리턴.
s.istitle()
s.capitalize() # 문자열의 맨 앞글자만 대문자로 바꾸어 리턴함

단어 치환

s.replace(기존값, 변경할값, 변경횟수)
s.maketrans("tps", "123") # t->1, p->2, s->3 로 치환

양옆 제거, 채우기

s.strip(제거할값)
s.lstrip(제거할값) # 왼쪽에서부터 특정값 제거
s.rstrip(제거할값)

s.zfill({integer}) # 문자열의 길이가 정수가 될때까지 왼쪽에 0을 채움
s.rjust({integer}, 원하는 값) # 길이가 정수가 될때까지 왼쪽에 원하는값을 채움
s.ljust({integer}, 원하는 값) # 오른쪽에 원하는 값을 채움
s.center({integer}, 원하는 값) # 양옆에 원하는 값을 채움. 홀수면 왼쪽에 하나 더채움

특정 문자열로 시작/끝나는지 체크

s.startswith("특정 문자열")  # 특정 문자열이 s 보다 길어도 에러안남
s.endswith("특정 문자열")

문자열이 모두 ~인지

s.isspace() # 모두 공백인가
s.isalpha() # 모두 알파벳인가 (한글 포함)
s.isalnum() # 모두 알파벳이나 숫자인가 
s.isdigit() # 모두 숫자인가

print의 끝 지정

print(a, end=" ")

format string

a=12
f'{a+2}asdf'  # 14asdf

아스키 코드

0~9의 아스키코드: 48~57
A~Z의 아스키코드: 65~90
a~z의 아스키코드: 97~122
대문자와 소문자의 차이: 32

ord(s) # 아스키코드로 변환
chr(i) # 문자로 변환

영문,숫자리스트

참고: https://blog.naver.com/jjys9047/221996234577

import string
string.ascii_lowercase # a~z까지 소문자가 있는 문자열
string.ascii_uppercase
string.digits # 0~9
string.hexdigits # 0~9a~fA~F

정규 표현식

참고: https://wikidocs.net/4308

사용법

# 1. 매칭시킬 패턴을 생성
import re
p = r'ab*' 

# 2. 문자열 검색
m = re.match(p, str1) # 문자열의 처음부터 매치되는지 조사
m = re.search(p, str1) # 문자열 전체를 검색하여 매치되는지 조사
m = re.findall(p, str1) # 매치되는 모든 문자열을 리스트로 리턴

# 3. match객체 메서드 사용
m.group() # 매치된 문자열을 리턴
m.start() # 매치 시작위치 리턴
m.end() # 매치 끝위치 리턴
	# re.match('abc', 'abc').end() == 3
m.span() # 매치 (시작, 끝) 리턴

패턴

[ ] 문자

[abc]는 ‘a, b, c 중 한 개의 문자와 매치’를 뜻함

[a-zA-Z] : 모든 알파벳
[0-9] : 모든 숫자
[ ] : 스페이스바
[aa] : 'a'를 찾음

\d : 숫자
\s : 화이트스페이스 (스페이스바, 탭, 줄바꿈등)
\w : 문자,숫자
\d, \s, \w 등을 대문자로 쓰면 반대로 매치된다.

. 문자,

\n을 제외한 모든 문자.

a.b
위 정규식의 의미는
'a + 모든문자 한개 + b'

반복 관련 문자

a*b
a가 0부터 무한히 반복 가능하다

a+b
a가 1부터 무한히 반복 가능하다

a{2}b
a가 반드시 2번 반복

a{2,4}b
a가 2~4번(4 포함) 반복

a{2,}
a{,3}

a?b
a가 0개거나 1개

시작과 끝

시작: ^
끝: $

pattern = r"^abc$"
match1 = re.search(pattern, "abc") # 일치
match2 = re.search(pattern, "abcd") # 불일치

Lookaroud

결과가 소모되지 않게함.

X(?=Y)  # Positive lookahead : X is followed by Y
X(?!Y)  # Negative lookahead
(?<=Y)X  # Positive lookbehind : X is after Y
(?<!Y)X  # Negative lookbehind

# 2글자가 연속적으로 글자인지 체크
p = r'(?=([a-z]{2}))'
re.findall(p, 'franc2e')  # ['fr', 'ra', 'an', 'nc']

숫자관련 함수

# 절대값
abs() 

# 몫과 나머지를 받아 튜플 형태로 리턴
divmod(8,3) # (2,2)

# 16진수로 리턴
hex(100) # 0x64
hex(0b10101) # 0x15
	
# 제곱하기
pow(2,3) # 2^3
2**3

# 숫자를 이진수 형태의 문자열로 표현
bin(4) # '0b100' 

# 이진수로 정수를 나타내는데 필요한 비트수 리턴
(0b000100).bit_length() # 3 (오른쪽 100 표현하는 3비트 필요)

# 숫자 연속비교
1 < x < 5 

math 모듈

import math
math.factorial(x)
math.sqrt(x) # 루트값
math.gcd(a,b) # 최대공약수
math.lcm(a,b) # 최소공배수; 3.9에서 추가됨
math.pi 
math.e 
math.ceil(x) # 올림
math.floor(x)
math.round(x)

진수변환

참고: https://url.kr/ikw1uo

n진수 -> 10진수

int(string, base)

10진수 -> n진수

코드 작성 필요

import string
digit = string.hexdigits
def convert(num, base):
	q, r = divmod(num, base)
	if q:
		return convert(q, base) + digit[r]
	else:
		return digit[r]

List

lst = []

lst.insert(요소, 위치) # 특정 위치에 요소 삽입

lst.append(요소) # 끝에 요소 하나 삽입. O(1)

lst.count(요소) # 요소의 개수를 셈

lst.clear() # 요소 모두 삭제

del lst[1]   # 특정 위치의 요소 삭제. O(n)

lst.remove(요소) # 특정 값을가진 첫번째 요소 삭제

lst.pop()  # 마지막 요소 리턴후 삭제. O(1)
lst.pop(0) # 첫번째 요소 리턴후 삭제. O(n)

lst.extend(병합할리스트) # 리스트 병합
	# lst1 + 병합할리스트 와 같으나 더 빠름
	# O(병합할 리스트의 원소수)

lst.index(요소) # 요소에 해당하는 첫번째 위치 검색
	# 없을경우 에러를 리턴함

lst.sort() # 내부적으로 정렬함. O(nlogn)

lst.reverse() # 리스트를 역순으로 치환

list(reversed(lst)) # 리스트 역순을 리턴

# 리스트 반복하기
[0] * 5 = [0,0,0,0,0]
# 참고로 lst = [[0,0,0]] * 3 이렇게 리스트를 초기화할 경우, 3개의 [0,0,0]은 모두 같은 객체로 인식이 된다. 즉 lst[0][0] = 2를 하면 lst는 [[2,0,0],[2,0,0],[2,0,0]] 이 된다.
# 따라서 올바른 방법은 [[0]*3 for _ in range(3)] 이다.


lst[i:j] # 리스트 슬라이싱. O(j-i)
	# 인덱스가 없는곳까지 넘어가도 에러없음

# 빈 2차원 리스트 생성하기
arr = [[] for _ in range(n)] # [[], [], [] ...]

# 2차원 리스트 1차원으로 합치기
# 속도는 느림
a = [[1,2,3], [4,5]]
sum(a, [])  # [1,2,3,4,5]

iterable 관련 함수

참고: https://dogrushdev.tistory.com/134

all(lst) # 모두 참이면 True, 거짓이 하나라도 있으면 False

any() # 하나라도 참이면 True

enumerate() # 순서가 있는 자료형을 입력인수로 받아 index, 값을 리턴
	for i, name in enumerate(['a','b','c','d'])

filter() # 첫번째 인수로 함수의 이름을 넣고 두번째 인수에 iterable을 넣으면 하나씩 함수에 집어넣어 True인것은 그대로 iterable에 넣어서 돌려줌. 
	non_capitalized = list(filter(str.upper, ["a", "b"])) #[a, b] 

map() # 첫번째 인수로 함수의 이름을 넣고 두번째 인수에 이터러블을 넣으면 하나씩 함수에 집어넣어 변화된 값을 그대로 객체형태로 돌려줌.
	capitalized = list(map(str.upper, ["a", "b"])) # [A, B]

sorted() # 정렬하여 리스트를 리턴
sorted("python") # ['h','n','o','p','t','y']
sorted({1,2,3}) # [1,2,3]
sorted(a, reverse=True) # 거꾸로 정렬
sorted(a, key=lambda x:(x[0], -x[1])) # 정렬 기준을 직접 주기

zip() # 같은 갯수를 가진 여러 iterable의 요소를 같은 인덱스끼리 묶어 리턴
	# zip 객체가 리턴되므로 list로 변환할 필요가 있음
	list(zip(['a','b','c'],['A','B','C'])) # [('a', 'A'), ('b', 'B'), ('c', 'C')]

set

s1 = set([1, 2, 3, 4, 5, 6])
	# set of tuple 가능, set of list, set of set 불가, set of frozenset가능
s1 = set(frozenset([1,2,3]), frozenset([3,4,5]))

# 교집합
s1 & s2
{4,5,6}

# 합집합
s1 | s2

# 차집합
s1 - s2

# 값 추가
s1.add(4)

# 값 여러개 추가
s1.update([4,5,6])

# 특정값 제거
s1.discard(2)
	# remove와 다르게 값이 없어도 에러가 나지않음

# 집합이 속하는지 여부
{1,2}.issubset({1,2,3}) # True
{1,2,3}.issuperset({1,2}) # True

# 두 집합간 교집합이 없는지 여부
{1,2,3}.isdisjoint({4,5}) # True

# 원소 내보내기 (순서가 보장되지 않음)
s1.pop()

dict

d = {1:'a'}

list(d) # 모든 키 반환

len(d) # 모든 아이템의 개수 반환

d.keys()

d.values()

d.items() # 키값쌍들

dict.fromkeys(seq, value) # seq를 키로하여 새로운 딕셔너리 생성. 기본 value는 None.

d.pop(key[, default]) # key에 해당하는 아이템을 삭제하고 value를 반환. 원소가 없으면 default 반환.

d.popitem() # 아이템을 pop하고 (key, value) 쌍을 반환.

d.setdefault(key[, default]) # key가 딕셔너리에 있으면 그 value을 반환하고, 없으면 key에 default에 해당하는 값을 넣고 default를 반환함.

d.update({otherdict}) # 다른 딕셔너리의 키값쌍을 덮어씌움

d | otherdict # 두 dict를 합치고 반환. otherdict이 우선권을 가짐

defaultdict

참고: https://velog.io/@dldbdud314/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%BD%94%ED%85%8C%EC%9A%A9-%EC%A0%95%EB%A6%AC

사전에 존재하지 않는 키라면 디폴트값을 넣어서 생성해준다.

from collections import defaultdict
mp = defaultdict(list, zip(a,b) )
mp["aa"].append("bb")
mp["aa"].append("cc")

heapq

참고: https://uni2237.tistory.com/56

PriorityQueue보다 빠른 힙

import heapq
arr = [3,2,1]
heapq.heapify(arr) # 리스트를 최소힙으로 바꿈. O(n)
	# arr[0]에 가장 작은 원소가 있다.
heapq.heappush(arr, value) # 원소 삽입
	# 최대 힙을 만드려면 부호를 반대로 해서 넣는다.
a = heapq.heappop(arr) # 가장 작은 원소 꺼냄

bisect

정렬된 리스트에서 값을 삽입할 인덱스를 알아냄

from bisect import bisect_left, bisect_right
left = bisect_left(arr, val) # 정렬된 리스트에 데이터를 삽입할 가장 왼쪽 인덱스
right = bisect_right(arr, val) # 정렬된 리스트에 데이터를 삽입할 가장 오른쪽 인덱스
bisect_right - bisect_left # 값이 특정 범위에 속하는 원소의 개수를 구함

deque

앞뒤로 빠르게 입출력이 가능한 자료구조. 큐 구현할때 사용

from collections import deque
deq = deque(iterable[,maxlen]) # maxlen을 넘으면 자동으로 popleft()를 함
deq.append(5)
deq.appendleft(1)
deq.copy() # 얕은복사본을 만듬
deq.extend(iterable) # 데크 오른쪽에 붙여넣음
deq.extendleft(iterable)
deq.insert(i, x) # i위치에 x를 삽입
deq.pop() 
deq.popleft()
deq.remove(value) #  첫번째 value를 제거함

Counter

iterable에서 내부원소가 몇번씩 등장했는지 알려줌

from collections import Counter
counter = Counter([1,2,3,4,1,1])
counter[1] # 3
counter[5] # 0

# 개수가 많은 원소순으로 리턴하기
counter.most_common() 
Counter('hello world').most_common(2) # 상위 2개 리턴. [('l', 3), ('o', 2)]

순열과 조합

from itertools import *
list(combinations(arr, 2)) # arr에서 2개씩 꺼내는 조합 튜플 형식으로 리턴
# 예: [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]

list(permutations(arr, 2)) # 2개씩 꺼내는 순열

list(product(arr, repeat=2)) # repeat 개수만큼 똑같은걸 여러번 꺼낼수있는 중복순열
list(product(*[[1,2,3],[4,5],[6]])) # 각 리스트에서 하나씩 꺼내기
# [(1, 4, 6), (1, 5, 6), (2, 4, 6), (2, 5, 6), (3, 4, 6), (3, 5, 6)]

list(combinations_with_replacement(arr,2)) # 2개씩 꺼내는 중복조합

개수

순열 : n Pr = n! / (n-r)! =
math.factorial(n) // math.factorial(n-r)
조합 : nCr = n! / (n-r)!r! =
math.factorial(n) // math.factorial(n-r) // math.factorial(r)
중복순열 : n𝛑r = nr =
n**r
중복조합: nHr = n+r-1Cr =
math.factorial(n+r-1) // math.factorial(n-1) // math.factorial(r)

참고: list로 변환해야 하는 함수들

  • reversed()
  • filter()
  • map()
  • zip()
  • combinations()
  • permutations()
  • product()
  • combinations_with_replacement()

연산자 순서

참고: https://dojang.io/mod/page/view.php?id=2461

참조 < 제곱 < 사칙연산 < 비트연산 < 비교 < 논리연산 < 할당

실행관련 함수

# 문자열을 실행
eval({실행할 문자열}) 

# 재귀호출 제한풀기
import sys
sys.setrecursionlimit(10**6)

# 빠르게 입력받기
import sys
input = sys.stdin.readline 
profile
문서는 독자를 위해 쓰는것

0개의 댓글

관련 채용 정보