본문 바로가기
프로그래밍/파이썬

파이썬 - 시퀀스(Sequence) 타입 심화

by ennak 2024. 12. 1.
반응형

파이썬의 시퀀스 타입

파이썬에서 시퀀스 타입은 데이터를 순서대로 저장하는 자료구조를 말한다. 리스트, 튜플, 문자열 등이 대표적인 시퀀스 타입이다. 이러한 시퀀스 타입의 데이터를 효과적으로 다루기 위해서는 슬라이싱과 인덱싱에 대한 깊이 있는 이해가 필요하다.


인덱싱의 기본과 응용

인덱싱은 시퀀스의 특정 위치에 있는 요소에 접근하는 방법이다. 파이썬에서 인덱스는 0부터 시작하며, 음수 인덱스를 사용하면 시퀀스의 끝에서부터 요소에 접근할 수 있다.

sequence = [1, 2, 3, 4, 5]
print(sequence[0])  # 출력: 1
print(sequence[-1])  # 출력: 5

인덱싱의 응용으로, 다차원 시퀀스에서도 사용할 수 있다. 예를 들어, 2차원 리스트에서는 다음과 같이 사용한다.

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix[1][2])  # 출력: 6

슬라이싱의 기본과 고급 기법

슬라이싱은 시퀀스의 일부분을 추출하는 강력한 기능이다. 기본 문법은 sequence[start:end:step]이다. 여기서 start는 시작 인덱스, end는 끝 인덱스(포함되지 않음), step은 간격을 의미한다.

sequence = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(sequence[2:7])  # 출력: [2, 3, 4, 5, 6]
print(sequence[::2])  # 출력: [0, 2, 4, 6, 8]
print(sequence[::-1])  # 출력: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

슬라이싱의 고급 기법으로는 다음과 같은 것들이 있다.

1. 음수 스텝 사용하기

print(sequence[7:2:-1])  # 출력: [7, 6, 5, 4, 3]

2. 시작 또는 끝 인덱스 생략하기

print(sequence[:5])  # 출력: [0, 1, 2, 3, 4]
print(sequence[5:])  # 출력: [5, 6, 7, 8, 9]

3. 슬라이스 객체 사용하기

s = slice(2, 7, 2)
print(sequence[s])  # 출력: [2, 4, 6]

문자열에서의 슬라이싱과 인덱싱

문자열도 시퀀스 타입이므로 슬라이싱과 인덱싱을 적용할 수 있다. 이를 통해 문자열 처리를 효율적으로 할 수 있다.

text = "Python Programming"
print(text[7:])  # 출력: Programming
print(text[::-1])  # 출력: gnimmargorP nohtyP

문자열에서 슬라이싱을 활용하면 부분 문자열을 쉽게 추출할 수 있다. 예를 들어, 파일 확장자를 추출하는 경우

filename = "document.pdf"
extension = filename[filename.rfind('.')+1:]
print(extension)  # 출력: pdf

리스트 컴프리헨션과 슬라이싱의 조합

리스트 컴프리헨션과 슬라이싱을 조합하면 강력한 데이터 처리 도구를 만들 수 있다. 예를 들어, 2차원 리스트에서 특정 열을 추출하는 경우

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
column_2 = [row[1] for row in matrix]
print(column_2)  # 출력: [2, 5, 8]

또는 짝수 인덱스의 요소만 추출하는 경우

sequence = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
even_indexed = [x for i, x in enumerate(sequence) if i % 2 == 0]
print(even_indexed)  # 출력: [0, 2, 4, 6, 8]

슬라이싱을 이용한 리스트 수정

슬라이싱은 리스트의 일부를 수정하는 데에도 사용될 수 있다. 이는 리스트의 요소를 삭제하거나 새로운 요소를 삽입할 때 유용하다.

numbers = [1, 2, 3, 4, 5]
numbers[1:4] = [20, 30]
print(numbers)  # 출력: [1, 20, 30, 5]

numbers[1:1] = [15, 25]
print(numbers)  # 출력: [1, 15, 25, 20, 30, 5]

이 방법은 del 키워드와 함께 사용하여 리스트의 일부를 삭제하는 데에도 활용할 수 있다.

numbers = [1, 2, 3, 4, 5]
del numbers[1:3]
print(numbers)  # 출력: [1, 4, 5]

다차원 배열에서의 슬라이싱

NumPy 라이브러리를 사용하면 다차원 배열에서도 고급 슬라이싱 기법을 적용할 수 있다. 이는 데이터 분석이나 과학 계산에서 매우 유용하다.

import numpy as np

arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]])

print(arr[:2, 1:3])
# 출력:
# [[2 3]
#  [6 7]]

print(arr[::2, ::2])
# 출력:
# [[1 3]
#  [9 11]]

슬라이싱과 인덱싱의 성능 고려사항

슬라이싱과 인덱싱은 매우 유용한 기능이지만, 대용량 데이터를 다룰 때는 성능에 주의를 기울여야 한다. 특히 큰 리스트나 문자열에서 슬라이싱을 사용할 때는 새로운 객체가 생성되므로 메모리 사용량이 증가할 수 있다.

예를 들어, 큰 리스트에서 역순으로 슬라이싱을 하는 경우

large_list = list(range(1000000))
reversed_list = large_list[::-1]  # 새로운 리스트 객체 생성

이 경우, reversed_list는 large_list의 모든 요소를 역순으로 복사한 새로운 리스트가 된다. 대용량 데이터에서는 이러한 연산이 메모리와 시간을 많이 소모할 수 있다.

대신, 이터레이터를 사용하면 메모리 효율성을 높일 수 있다.

reversed_iterator = reversed(large_list)

이 방법은 실제로 리스트를 역순으로 변환하지 않고, 필요할 때마다 요소를 역순으로 접근할 수 있게 해준다.


문자열 처리에서의 슬라이싱 활용

문자열 처리에서 슬라이싱은 매우 유용하게 사용된다. 예를 들어, 문자열을 뒤집거나 특정 부분을 추출하는 데 효과적이다.

1. 팰린드롬 확인

def is_palindrome(s):
    return s == s[::-1]

print(is_palindrome("racecar"))  # 출력: True
print(is_palindrome("hello"))    # 출력: False

2. URL에서 도메인 추출

url = "https://www.example.com/path/to/page"
domain = url.split("//")[-1].split("/")[0]
print(domain)  # 출력: www.example.com

3. 문자열 포맷팅과 슬라이싱

def format_credit_card(number):
    return f"{number[:4]} {number[4:8]} {number[8:12]} {number[12:]}"

card_number = "1234567890123456"
print(format_credit_card(card_number))  # 출력: 1234 5678 9012 3456

슬라이싱을 이용한 알고리즘 최적화

슬라이싱을 적절히 활용하면 알고리즘의 성능을 향상시킬 수 있다. 예를 들어, 리스트의 로테이션을 구현할 때 슬라이싱을 사용하면 간단하고 효율적으로 구현할 수 있다.

def rotate_list(lst, k):
    k = k % len(lst)  # k가 리스트 길이보다 클 경우 처리
    return lst[k:] + lst[:k]

original = [1, 2, 3, 4, 5]
rotated = rotate_list(original, 2)
print(rotated)  # 출력: [3, 4, 5, 1, 2]

이 방법은 추가적인 메모리를 사용하지 않고도 리스트를 효과적으로 회전시킬 수 있다.


슬라이싱과 인덱싱의 응용: 데이터 분석

데이터 분석 분야에서 슬라이싱과 인덱싱은 매우 중요한 역할을 한다. 특히 pandas 라이브러리를 사용할 때 이러한 기술이 자주 활용된다.

import pandas as pd

# 샘플 데이터프레임 생성
df = pd.DataFrame({
    'A': range(1, 6),
    'B': range(10, 15),
    'C': range(100, 105)
})

# 특정 열 선택
print(df['A'])

# 여러 열 선택
print(df[['A', 'C']])

# 행 슬라이싱
print(df[1:3])

# loc를 이용한 레이블 기반 인덱싱
print(df.loc[1:3, 'A':'B'])

# iloc를 이용한 정수 위치 기반 인덱싱
print(df.iloc[0:2, 0:2])

이러한 기법들을 사용하면 대규모 데이터셋에서 필요한 부분만 효과적으로 추출하고 분석할 수 있다.


슬라이싱의 응용: 이미지 처리

컴퓨터 비전 분야에서도 슬라이싱은 중요한 역할을 한다. 예를 들어, PIL(Python Imaging Library)이나 OpenCV를 사용하여 이미지를 처리할 때 슬라이싱을 활용할 수 있다.

from PIL import Image
import numpy as np

# 이미지 로드
img = Image.open('example.jpg')
img_array = np.array(img)

# 이미지의 일부분 추출
cropped = img_array[100:300, 200:400]

# 이미지 회전 (90도)
rotated = np.rot90(img_array)

# 이미지 좌우 반전
flipped = img_array[:, ::-1]

# 결과 저장
Image.fromarray(cropped).save('cropped.jpg')
Image.fromarray(rotated).save('rotated.jpg')
Image.fromarray(flipped).save('flipped.jpg')

이러한 방식으로 이미지의 특정 부분을 추출하거나 변형하는 작업을 간단하게 수행할 수 있다.

반응형