i vs arr[i])값을 비교해야 하는 조건문에는
i가 아니라arr[i].
# ❌ 틀린 코드
for i in range(len(arr)):
if i % 2 == 0 and i >= 50: # i는 인덱스일 뿐
...
# ✅ 고친 코드
for i in range(len(arr)):
if arr[i] % 2 == 0 and arr[i] >= 50:
...
i = 창고 선반 번호 / arr[i] = 그 선반 위의 물건for x in arr:로 아예 값을 직접 꺼내 회피% 홀짝 판별 / // 정수 나눗셈 vs / 실수 나눗셈.index() 쓰기 전에 "없으면?"
.index()는 대상이 없으면ValueError. 존재 확인이 먼저.
# ❌ 틀린 코드 — 2가 없으면 터짐
idx = arr.index(2)
# ✅ 고친 코드
if 2 in arr:
idx = arr.index(2)
else:
... # 없을 때 처리
0을 "못 찾음" 신호로 쓰면 안 됨 → 0도 유효한 인덱스
[a:b]는 a 포함, b 제외. 오른쪽 슬라이싱에서 경계 원소 딸려 들어감 주의.
# ❌ 틀린 코드 — 기준 원소가 결과에 포함됨
return arr[idx:]
# ✅ 고친 코드 — 기준 다음부터
return arr[idx+1:]
s[:-0]은 전체가 아니라 빈 문자열 (-0 == 0이라 [:0]이 됨)[a:b] 경계를 손으로 추적문자열 메서드는 원본을 안 바꾼다. 반환값을 받아야 함.
# ❌ 틀린 코드 — 원본 그대로
s.lower()
s.replace("a", "b")
# ✅ 고친 코드 — 반환값 대입
s = s.lower()
s = s.replace("a", "b")
enumerate 루프에서 v += n도 복사본을 수정할 뿐 원본 리스트는 안 바뀜# ❌ 원본 리스트 안 바뀜
for idx, v in enumerate(arr):
v += n
# ✅ 인덱스로 직접 접근
for idx in range(len(arr)):
arr[idx] += n
list() vs split()문자 하나씩은
list(), 구분자로 덩어리 나누기는split().
list("abc") # ['a', 'b', 'c'] 문자 단위
"a b c".split() # ['a', 'b', 'c'] 공백 기준 덩어리
"a,b,c".split(",") # ['a', 'b', 'c'] 구분자 기준
"abc".split("") # ❌ ValueError — 빈 구분자 불가
for ch in s도 가능list() → 처리 → "".join()# 문자열 뒤집기 예시
s = "hello"
result = "".join(list(s)[::-1]) # 'olleh'
defaultdict — 없는 키 자동 초기화없는 키를 조회해도 기본값으로 자동 생성. 그룹핑에 강력.
from collections import defaultdict
# 길이별로 문자열 그룹핑
d = defaultdict(list)
for s in strArr:
d[len(s)].append(s) # 키가 없어도 빈 리스트 자동 생성
defaultdict(int)은 카운팅, defaultdict(list)은 그룹핑/인접리스트에 자주 씀len(s)를 키로 (문자열 자체를 키로 쓰면 안 됨)Counter — 빈도 계산 완제품빈도 세기 전용.
defaultdict보다 간결하지만 동작 차이 주의.
from collections import Counter
cnt = Counter(strArr) # 각 원소 빈도
max_freq = max(cnt.values()) # 최대 빈도
cnt.most_common(1) # [('a', 3)] — 리스트 반환!
cnt.most_common(1)[0][0] # 'a' (값)
cnt.most_common(1)[0][1] # 3 (횟수)
Counter vs defaultdict 차이 (주의할 실수)
| 구분 | 동작 |
|---|---|
| 없는 키 조회 | Counter는 0 반환하지만 키로 저장 안 함 |
.update() | dict는 덮어쓰기 / Counter는 누적 |
뺄셈 - | 음수 버림 |
.subtract() | 음수 보존 |
코테 활용 패턴
# 애너그램 판별
Counter(s1) == Counter(s2)
# 부분집합 검사 (s2가 s1에 다 포함되나)
not (Counter(s2) - Counter(s1))
[[0]*n]*n은 참조 공유 버그. 컴프리헨션이 정답.
# ❌ 틀린 코드 — 모든 행이 같은 리스트를 가리킴
arr = [[0]*n]*n
arr[0][0] = 1 # 모든 행의 [0]이 같이 1로 바뀜!
# ✅ 고친 코드 — 행마다 독립된 리스트
arr = [[0]*n for _ in range(n)]
arr[i][j] = i행 j열zip, enumerate, len, 슬라이싱if 구분
- 필터형
if(뒤)와 삼항if-else(앞)는 역할이 다르다. 섞으면 문법 에러.
# 필터형 if — for 뒤. 조건 안 맞으면 아예 제외
[x for x in arr if x > 0]
# 삼항 if-else — 표현식 자리. 모두에게 값 배정
[x if x > 0 else 0 for x in arr]
ord() / chr()와 오프셋 연산문자↔숫자 변환 후, 기준 문자를 빼서 인덱스로 매핑.
ord('A') # 65 문자 → 숫자
chr(65) # 'A' 숫자 → 문자
# 대문자 A~Z를 0~25 인덱스로
idx = ord(ch) - ord('A') # ord('A') = 65
ord('a') - 26 = 97 - 26 = 71elif로
else로 뭉뚱그리면 비알파벳 입력이 조용히 오답을 만든다.
# ❌ 틀린 코드 — 숫자·기호가 else로 흘러 음수 인덱싱
if ch.isupper():
count[ord(ch) - 65] += 1
else:
count[ord(ch) - 71] += 1 # 비알파벳이면 엉뚱한 곳 +1
# ✅ 고친 코드 — 명시적으로 걸러냄
if ch.isupper():
count[ord(ch) - 65] += 1
elif ch.islower():
count[ord(ch) - 71] += 1
# 그 외는 무시
isupper(), islower(), isalpha(), isdigit()