Python

[Python] Dictionary 배열에서 조건에 맞는 원소 찾기 - 1

비번변경 2022. 10. 6. 18:12

개요

Dictionary를 원소로 하는 리스트를 다루던 중, 특정 속성의 값에 해당하는 원소를 찾을 필요성이 생겼다.

탐색에 사용할 속성은 1개이고, 그 속성의 값은 배열에서 unique 하지만 존재하지 않을 수도 있다. 배열 내 찾는 원소가 없을 때는 None, 또는 검색한 속성과 값을 제외하고는 값이 빈 Dictionary를 반환하고자 한다.

 

 

next(iterable, default)

next 함수는 반복 가능한 객체의 다음 요소를 반환하는 개체이다. default는 마지막 요소를 반환할 이후 반환할 값을 설정할 수 있다.

 

예로 들어 아래의 people dictionary 리스트에서 name이 Tom인 객체는 다음과 같이 찾을 수 있다.

people = [
    {"name": "Tom", "age": 10},
    {"name": "Mark", "age": 5},
    {"name": "Pam", "age": 7}
]

# 찾는 객체가 존재하는 경우
print(next((item for item in people if item.get(k) == 'Tom'), None))

# 찾는 객체가 존재하지 않는 경우
print(next((item for item in people if item.get(k) == 'Tome'), None))

next

 

 

조금 자주 사용할 것 같아 함수로 만들어 보았다. 매개변수로 전달할 것은 리스트와 검색에 사용한 키, 값이다.

def get_item(ob, **kwargs):
    k = list(kwargs.keys())[0] # dict_keys 객체는 슬라이싱이 불가능해 리스트형 변환이 필요하다.
    v = list(kwargs.values())[0]
    return next((item for item in ob if item.get(k) == v), None)


people = [
    {"name": "Tom", "age": 10},
    {"name": "Mark", "age": 5},
    {"name": "Pam", "age": 7}
]

print(get_item(people, name="Tom"))
print(get_item(people, name="Tome"))

함수로 분리

 

 

기본값을 Dictionary로 변경

위의 예시에서는 배열 내에 속성에 맞는 객체가 없는 경우 None을 반환하는데, 이번에는 None이 아니라 Dictionary를 반환하려고 한다.

단, 기본값으로 반환하는 Dictionary는 배열 내 Dictionary의 모든 키를 가진다. 그리고 탐색에 사용한 키를 제외한 나머지 키의 값은 None으로 한다. 탐색에 사용하는 키는 탐색한 값으로 설정한다. 
즉, 이 글의 경우에는 아래와 같은 Dictionary가 반환되어야 한다. 탐색에 사용하는 키가 배열 내 dictionary에 없는 경우는 생각하지 않겠다.

# Dictionary 내에 key가 존재하는 경우
{'name': 'Tom', 'age': None }

# Dictionary 내에 key가 존재하지 않는 경우
{'name': None, 'age': None, 'nam': 'Tom'}

 

기본으로 반환할 Dictionary는 dict.fromkeys(key, val) 함수를 이용해 생성한다. 매개변수로 key를 튜플 등으로 전달하며, 기본값 설정이 필요하면 추가로 전달할 수 있다. 전달하지 않으면 None으로 설정된다.

def get_item(ob, **kwargs):
    k = list(kwargs.keys())[0]
    v = list(kwargs.values())[0]

    tmp = dict.fromkeys(ob[0].keys())
    tmp[k] = v

    return next((item for item in ob if item.get(k) == v), tmp)


people = [
    {"name": "Tom", "age": 10},
    {"name": "Mark", "age": 5},
    {"name": "Pam", "age": 7}
]

print(get_item(people, name="Tom"))
print(get_item(people, nam="Tom"))

 

 

참고 문서

https://stackoverflow.com/questions/8653516/python-list-of-dictionaries-search