아래는 데이터 카드를 관리하기 위한 데이터 카드 컨테이너를 구현한 사용자 정의 클래스의 샘플 코드입니다. 이 클래스는 여러 데이터 카드를 저장하고, 검색 및 필터링 등의 기능을 제공합니다.

from datetime import datetime
from typing import List, Optional, Dict

class DataCard:
    """데이터 카드 클래스"""
    def __init__(self, name: str, description: str, tags: Optional[List[str]] = None):
        self.name = name
        self.description = description
        self.created_at = datetime.now()
        self.updated_at = datetime.now()
        self.tags = tags or []

    def update_description(self, new_description: str):
        self.description = new_description
        self.updated_at = datetime.now()

    def add_tag(self, tag: str):
        if tag not in self.tags:
            self.tags.append(tag)
            self.updated_at = datetime.now()

    def remove_tag(self, tag: str):
        if tag in self.tags:
            self.tags.remove(tag)
            self.updated_at = datetime.now()

    def display(self):
        print(f"Data Card: {self.name}")
        print(f"Description: {self.description}")
        print(f"Created At: {self.created_at}")
        print(f"Updated At: {self.updated_at}")
        print(f"Tags: {', '.join(self.tags)}")

class DataCardContainer:
    """데이터 카드 컨테이너 클래스"""
    def __init__(self):
        self.cards: List[DataCard] = []

    def add_card(self, card: DataCard):
        """컨테이너에 데이터 카드 추가"""
        if any(existing_card.name == card.name for existing_card in self.cards):
            raise ValueError(f"A card with the name '{card.name}' already exists.")
        self.cards.append(card)

    def remove_card(self, card_name: str):
        """컨테이너에서 데이터 카드 삭제"""
        self.cards = [card for card in self.cards if card.name != card_name]

    def get_card(self, card_name: str) -> Optional[DataCard]:
        """이름으로 데이터 카드 검색"""
        for card in self.cards:
            if card.name == card_name:
                return card
        return None

    def filter_by_tag(self, tag: str) -> List[DataCard]:
        """특정 태그를 포함한 데이터 카드 필터링"""
        return [card for card in self.cards if tag in card.tags]

    def display_all(self):
        """모든 데이터 카드 출력"""
        if not self.cards:
            print("No data cards available.")
        for card in self.cards:
            card.display()
            print("-" * 40)

# 사용 예제
if __name__ == "__main__":
    # 데이터 카드 생성
    card1 = DataCard(name="Customer Data", description="Contains customer demographics.", tags=["customer", "demographics"])
    card2 = DataCard(name="Sales Data", description="Sales performance data.", tags=["sales", "performance"])
    card3 = DataCard(name="Survey Data", description="Customer feedback survey results.", tags=["survey", "feedback"])

    # 컨테이너 생성 및 카드 추가
    container = DataCardContainer()
    container.add_card(card1)
    container.add_card(card2)
    container.add_card(card3)

    # 모든 카드 출력
    print("All Data Cards:")
    container.display_all()

    # 특정 카드 검색
    print("\nSearching for 'Sales Data':")
    sales_card = container.get_card("Sales Data")
    if sales_card:
        sales_card.display()

    # 특정 태그로 필터링
    print("\nFiltering cards with tag 'customer':")
    customer_cards = container.filter_by_tag("customer")
    for card in customer_cards:
        card.display()

코드 설명

  1. DataCard 클래스:
    • 각 데이터 카드를 표현하며 이름, 설명, 태그, 생성/수정 시간을 포함.
    • 태그 추가/삭제 및 설명 업데이트 기능 제공.
  2. DataCardContainer 클래스:
    • 여러 데이터를 관리할 컨테이너로, 다음 주요 기능 포함:
      • 카드 추가: 이름이 중복되지 않도록 확인.
      • 카드 삭제: 이름으로 특정 카드를 삭제.
      • 카드 검색: 이름으로 특정 카드 반환.
      • 태그 필터링: 특정 태그를 포함한 카드 목록 반환.
      • 전체 출력: 저장된 모든 데이터 카드를 출력.
  3. 사용 예제:
    • 세 개의 데이터 카드를 생성하고 컨테이너에 추가.
    • 모든 카드 출력, 특정 카드 검색, 특정 태그로 필터링.

실행 결과 (예시):

All Data Cards:
Data Card: Customer Data
Description: Contains customer demographics.
Created At: 2025-01-07 12:00:00.123456
Updated At: 2025-01-07 12:00:00.123456
Tags: customer, demographics
----------------------------------------
Data Card: Sales Data
Description: Sales performance data.
Created At: 2025-01-07 12:00:01.123456
Updated At: 2025-01-07 12:00:01.123456
Tags: sales, performance
----------------------------------------
Data Card: Survey Data
Description: Customer feedback survey results.
Created At: 2025-01-07 12:00:02.123456
Updated At: 2025-01-07 12:00:02.123456
Tags: survey, feedback
----------------------------------------

Searching for 'Sales Data':
Data Card: Sales Data
Description: Sales performance data.
Created At: 2025-01-07 12:00:01.123456
Updated At: 2025-01-07 12:00:01.123456
Tags: sales, performance

Filtering cards with tag 'customer':
Data Card: Customer Data
Description: Contains customer demographics.
Created At: 2025-01-07 12:00:00.123456
Updated At: 2025-01-07 12:00:00.123456
Tags: customer, demographics

이 클래스 구조는 여러 데이터 카드를 체계적으로 관리하고 쉽게 검색, 필터링, 업데이트할 수 있도록 설계되었습니다.

데이터 카드 목록에서 필터 기능을 효율적으로 구현하기 위해 어댑터 디자인 패턴을 사용할 수 있습니다. 어댑터 패턴을 사용하면 기존 데이터 카드 구조에 영향을 주지 않고도, 필터링 기능을 다양한 형태로 확장하여 일관성 있게 사용할 수 있습니다. 이를 통해 필터 조건을 유연하게 조합하거나 새로운 필터를 추가하기가 수월해집니다.

어댑터 패턴을 활용한 필터 모델 설명

어댑터 패턴은 호환되지 않는 인터페이스를 일관된 인터페이스로 변환하여 사용자가 같은 방식으로 다양한 객체를 활용할 수 있도록 해줍니다.

  1. 데이터 카드 모델: 필터링할 데이터 카드 리스트를 포함한 클래스입니다. 이를 통해 특정 조건에 맞는 필터 결과를 얻습니다.

  2. 필터 인터페이스(Filter Interface): 필터 조건을 정의한 기본 인터페이스입니다. 각 필터는 특정 조건을 만족하는 카드를 필터링하기 위해 이 인터페이스를 구현합니다.

  3. 구체적인 필터 클래스: 특정 조건을 구현하는 클래스입니다. 예를 들어, ScoreFilter는 점수 조건 필터링을, DateFilter는 날짜 조건 필터링을 구현합니다.

  4. 어댑터 클래스: 데이터 카드 모델의 필터 기능을 어댑터로 감싸어, 필터 인터페이스의 구현체를 통해 카드 리스트를 필터링하는 역할을 합니다.

이 구조를 사용하면 필터 조건을 새롭게 추가하거나 조합하여 사용할 수 있습니다.

예제 코드: 어댑터 패턴을 활용한 필터 모델 구현

from typing import List, Protocol

# 데이터 카드 필터 인터페이스 정의
class FilterInterface(Protocol):
    def apply(self, data_card: dict) -> bool:
        ...

# 데이터 카드 모델 정의
class GamePlayDataCardModel(list):
    def add_card(self, player_id, player_name, level, score, date):
        card = {
            "player_id": player_id,
            "player_name": player_name,
            "level": level,
            "score": score,
            "date": date
        }
        self.append(card)

# 구체적인 필터 클래스 정의
class ScoreFilter:
    def __init__(self, min_score: int):
        self.min_score = min_score

    def apply(self, data_card: dict) -> bool:
        return data_card["score"] >= self.min_score

class DateFilter:
    def __init__(self, play_date: str):
        self.play_date = play_date

    def apply(self, data_card: dict) -> bool:
        return data_card["date"] == self.play_date

class LevelRangeFilter:
    def __init__(self, min_level: int, max_level: int):
        self.min_level = min_level
        self.max_level = max_level

    def apply(self, data_card: dict) -> bool:
        return self.min_level <= data_card["level"] <= self.max_level

# 필터 어댑터 클래스 정의
class FilterAdapter:
    def __init__(self, data_model: GamePlayDataCardModel):
        self.data_model = data_model

    def filter(self, filters: List[FilterInterface]) -> List[dict]:
        # 모든 필터 조건을 충족하는 카드만 필터링
        return [
            card for card in self.data_model
            if all(f.apply(card) for f in filters)
        ]

# 데이터 카드 모델 인스턴스 생성
game_data = GamePlayDataCardModel()

# 데이터 카드 추가
game_data.add_card("player123", "GamerOne", level=5, score=1500, date="2024-10-21")
game_data.add_card("player456", "GamerTwo", level=3, score=1200, date="2024-10-21")
game_data.add_card("player123", "GamerOne", level=6, score=1800, date="2024-10-22")
game_data.add_card("player789", "GamerThree", level=4, score=900, date="2024-10-22")

# 어댑터를 통한 필터링
adapter = FilterAdapter(game_data)

# 필터 설정: 점수가 1300 이상이고, 날짜가 2024-10-21인 카드
filters = [ScoreFilter(min_score=1300), DateFilter(play_date="2024-10-21")]
filtered_cards = adapter.filter(filters)
print("Filtered Cards with score >= 1300 and date 2024-10-21:", filtered_cards)

# 다른 필터 조합: 레벨이 3에서 5 사이인 카드
filters = [LevelRangeFilter(min_level=3, max_level=5)]
filtered_cards = adapter.filter(filters)
print("Filtered Cards with level between 3 and 5:", filtered_cards)

출력 예시

Filtered Cards with score >= 1300 and date 2024-10-21: [
    {'player_id': 'player123', 'player_name': 'GamerOne', 'level': 5, 'score': 1500, 'date': '2024-10-21'}
]

Filtered Cards with level between 3 and 5: [
    {'player_id': 'player456', 'player_name': 'GamerTwo', 'level': 3, 'score': 1200, 'date': '2024-10-21'},
    {'player_id': 'player789', 'player_name': 'GamerThree', 'level': 4, 'score': 900, 'date': '2024-10-22'}
]

코드 설명

  • FilterInterface: 필터 조건을 정의한 프로토콜로, 필터 클래스는 apply 메서드를 구현하여 조건에 맞는지 여부를 판별합니다.
  • 구체적인 필터 클래스: ScoreFilter, DateFilter, LevelRangeFilter는 각각 점수, 날짜, 레벨 범위를 기준으로 필터링합니다.
  • FilterAdapter 클래스: 필터 어댑터가 데이터 모델을 감싸고, 여러 필터 조건을 적용하여 데이터 카드를 필터링하는 역할을 합니다. filter 메서드는 전달받은 필터 리스트를 모두 적용해 모든 조건을 만족하는 카드만 반환합니다.

이 구조의 장점

  • 유연한 필터링 조건 추가: 필터를 클래스로 정의하고 어댑터를 통해 관리하므로, 새로운 필터 조건을 쉽게 추가할 수 있습니다.
  • 조합 가능성: 여러 필터 조건을 동시에 사용할 수 있어 복잡한 필터링 조건도 적용할 수 있습니다.
  • 확장성: 필터 인터페이스만 구현하면 새로운 필터를 쉽게 적용할 수 있어 구조 확장이 용이합니다.

어댑터 디자인 패턴을 통해 필터 조건을 일관되게 적용할 수 있으며, 필터링 조건 추가와 조합이 용이해 다양한 데이터 관리와 분석에 활용할 수 있습니다.

데이터 카드 자료구조에서 필터 기능을 구현하면 특정 조건에 맞는 데이터를 쉽게 조회할 수 있어 데이터 관리와 분석에 유용합니다. 필터는 예를 들어, 게임 플레이 데이터를 다룰 때 특정 점수 이상의 플레이어를 조회하거나 특정 날짜에 플레이한 기록만을 가져오는 경우에 사용할 수 있습니다.

필터 구현 설명

데이터 카드 자료구조에서 필터를 구현하려면 데이터 카드를 저장하는 클래스에 필터 메서드를 추가하여 조건에 맞는 데이터를 반환하도록 합니다. 파이썬의 filter 함수를 사용하거나, 리스트 컴프리헨션을 사용해 특정 조건에 맞는 카드만 추출할 수 있습니다.

예제 코드: 필터 메서드가 포함된 데이터 카드 클래스

다음은 GamePlayDataCardModel 클래스에 특정 조건에 맞는 카드를 필터링하는 메서드를 구현한 예제입니다.

# 데이터 카드 모델 클래스 정의
class GamePlayDataCardModel(list):
    def add_card(self, player_id, player_name, level, score, date):
        card = {
            "player_id": player_id,
            "player_name": player_name,
            "level": level,
            "score": score,
            "date": date
        }
        self.append(card)

    def filter_by_score(self, min_score):
        # 점수가 min_score 이상인 카드만 반환
        return [card for card in self if card["score"] >= min_score]

    def filter_by_date(self, play_date):
        # 특정 날짜에 플레이한 카드만 반환
        return [card for card in self if card["date"] == play_date]

    def filter_by_level_range(self, min_level, max_level):
        # 레벨이 특정 범위(min_level 이상, max_level 이하)에 있는 카드만 반환
        return [card for card in self if min_level <= card["level"] <= max_level]

# 데이터 카드 모델 인스턴스 생성
game_data = GamePlayDataCardModel()

# 데이터 카드 추가
game_data.add_card("player123", "GamerOne", level=5, score=1500, date="2024-10-21")
game_data.add_card("player456", "GamerTwo", level=3, score=1200, date="2024-10-21")
game_data.add_card("player123", "GamerOne", level=6, score=1800, date="2024-10-22")
game_data.add_card("player789", "GamerThree", level=4, score=900, date="2024-10-22")

# 필터링 예제: 점수가 1300 이상인 카드
high_score_cards = game_data.filter_by_score(1300)
print("Cards with score >= 1300:", high_score_cards)

# 필터링 예제: 2024-10-21에 플레이한 카드
date_filtered_cards = game_data.filter_by_date("2024-10-21")
print("Cards with play date 2024-10-21:", date_filtered_cards)

# 필터링 예제: 레벨이 3에서 5 사이인 카드
level_filtered_cards = game_data.filter_by_level_range(3, 5)
print("Cards with level between 3 and 5:", level_filtered_cards)

출력 예시

Cards with score >= 1300: [
    {'player_id': 'player123', 'player_name': 'GamerOne', 'level': 5, 'score': 1500, 'date': '2024-10-21'},
    {'player_id': 'player123', 'player_name': 'GamerOne', 'level': 6, 'score': 1800, 'date': '2024-10-22'}
]

Cards with play date 2024-10-21: [
    {'player_id': 'player123', 'player_name': 'GamerOne', 'level': 5, 'score': 1500, 'date': '2024-10-21'},
    {'player_id': 'player456', 'player_name': 'GamerTwo', 'level': 3, 'score': 1200, 'date': '2024-10-21'}
]

Cards with level between 3 and 5: [
    {'player_id': 'player456', 'player_name': 'GamerTwo', 'level': 3, 'score': 1200, 'date': '2024-10-21'},
    {'player_id': 'player789', 'player_name': 'GamerThree', 'level': 4, 'score': 900, 'date': '2024-10-22'}
]

코드 설명

  • filter_by_score 메서드: min_score 이상의 점수를 가진 카드를 필터링하여 반환합니다.
  • filter_by_date 메서드: 특정 날짜에 플레이된 카드만 필터링하여 반환합니다.
  • filter_by_level_range 메서드: 특정 레벨 범위 내(min_level ~ max_level)에 속하는 카드만 필터링하여 반환합니다.

이 구조의 장점

  • 가독성: 조건에 맞는 필터링을 메서드로 정의하여 코드 가독성이 높습니다.
  • 재사용성: 다양한 조건에 따라 데이터를 쉽게 필터링할 수 있습니다.
  • 유연성: 카드 데이터가 추가되더라도 동일한 필터링 메서드를 사용할 수 있어 유연한 데이터 관리가 가능합니다.

이와 같은 필터 기능을 활용하면, 큰 데이터에서 필요한 정보만 추출하거나 특정 조건의 데이터만 분석하는 데 유리합니다.

+ Recent posts