Python에서 객체 목록 검색


94

데이터 요소를 보유하기 위해 C 스타일 구조체와 유사하게 작동하는 간단한 클래스를 생성한다고 가정 해 보겠습니다. 특정 값과 동일한 속성을 가진 개체에 대한 개체 목록을 검색하는 방법을 알아 내려고합니다. 아래는 내가하려는 작업을 설명하는 간단한 예입니다.

예를 들면 :

class Data:
    pass

myList = []

for i in range(20):
    data = Data()
    data.n = i
    data.n_squared = i * i
    myList.append(data)

n == 5 인 요소가 포함되어 있는지 확인하기 위해 myList 목록을 검색하는 방법은 무엇입니까?

저는 파이썬 문서를 검색하고 검색해 왔으며 목록 이해력으로 이것을 할 수 있다고 생각하지만 확실하지 않습니다. 그런데 Python 2.4.3을 사용해야하므로 새로운 gee-whiz 2.6 또는 3.x 기능을 사용할 수 없습니다.


의도하지 않은 예일 수 있습니다. myList = [Data (). n == 0, Data (). n = 1, ...] 여기서 data.n은 range ()에 의해 할당되고 data.n은 myList에 대한 색인. 따라서 인덱스 값으로 myList를 참조하여 Data () 인스턴스를 가져올 수 있습니다. 물론 나중에 myList [0] .n = 5.2 등을 수정할 수 있습니다. 그리고 그 예는 아마도 지나치게 단순화되었을 것입니다.
DevPlayer

답변:


139

목록 이해도와 일치하는 모든 요소 의 목록을 가져올 수 있습니다 .

[x for x in myList if x.n == 30]  # list of all elements with .n==30

목록에 일치 하는 요소가 포함되어 있는지 확인하고 (상대적으로) 효율적으로 수행하려면 다음을 수행 할 수 있습니다.

def contains(list, filter):
    for x in list:
        if filter(x):
            return True
    return False

if contains(myList, lambda x: x.n == 3)  # True if any element has .n==3
    # do stuff

25
또는 any (custom_filter (x) for x in myList if xn == 30) 이것은 단지 "contains"함수를 내장 기능으로합니다.
nosklo

nosklo의 구문 오류-생성기 주변에 추가 () 세트가 필요합니다.
gahooa

별로. 그것을 시도하고보십시오.
Robert Rossney

1
이 답변을 gahooa ( stackoverflow.com/a/598602/2349267 ) 와 함께 병합하는 것이 좋습니다 .
로마 황

77

간단하고 우아하며 강력 함 :

내장과 결합 된 생성기 표현… (python 2.5+)

any(x for x in mylist if x.n == 10)

any()다음과 같이 정의 된 Python 내장 기능을 사용합니다 .

any (iterable) iterable의 -> 요소가 true이면 True를 반환합니다. 다음과 동일 :

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

좋은. 참고로 어떤 괄호를 저장하기 위해 (xn == 10이면 mylist에서 x에 대해 x) 괄호를 저장할 수 있습니다 (== 아님도 ==).
Jacob Gabrielson

내가 사용을 선호 any(x for x in mylist if x['n'] == 10)하지만, 좋은 생각
알렉스 몬토야

47

완전성을 위해, 작동 할 수있는 가장 간단한 것을 잊지 말자.

for i in list:
  if i.n == 5:
     # do something with it
     print "YAY! Found one!"

39
[x for x in myList if x.n == 30]               # list of all matches
[x.n_squared for x in myList if x.n == 30]     # property of matches
any(x.n == 30 for x in myList)                 # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30]  # indices of all matches

def first(iterable, default=None):
  for item in iterable:
    return item
  return default

first(x for x in myList if x.n == 30)          # the first match, if any

1
이것은 아마도 가장 일반적인 사용 사례 인 "first"방법 때문에 좋은 대답입니다.
galarant

감사합니다! 경기 지수는 내가 찾던 것이었다. 다른 필드에 액세스하기 위해 목록을 직접 색인화하는 데 사용하는 바로 가기가 있습니까? 이제 목록 항목의 목록을 얻습니다 (항목이 하나뿐이므로 항목이 하나 인 목록입니다). 인덱스를 얻으려면 목록을 인덱싱하는 데 사용하기 전에 result [0]을 수행해야합니다. 질문의 예에서, 나는 특정 N에서 n_squared 액세스하려는 : myList에를 [myList.n의 인덱스 == 5] .n_squared
Frieke

32
filter(lambda x: x.n == 5, myList)

25
Python을 배우고 싶은 사람에게는 람다를 이해하는 것이 기본입니다.
vartec

2
음, 예와 아니오-list comprehensions 및 operator.attrgetter와 같은 주요 기능 정렬 기능을 사용하면 lambdas를 거의 사용하지 않습니다 .
Ben Hoyt 2012 년

9

를 사용 in하여 컬렉션에서 항목을 찾고 목록 이해를 통해 관심있는 필드를 추출 할 수 있습니다. 이것은 목록, 집합, 튜플 및 __contains__또는 정의하는 모든 항목에 대해 작동합니다 __getitem__.

if 5 in [data.n for data in myList]:
    print "Found it"

또한보십시오:


4

클래스에 __eq____hash__메서드를 추가해야 Data합니다.__dict__ 속성이 같은지 (동일한 속성) 값이 같은지 확인할 수 있습니다.

그렇게했다면 다음을 사용할 수 있습니다.

test = Data()
test.n = 5

found = test in myList

in경우 키워드 검사 testmyList .

n속성 만 원하는 경우 다음을 Data사용할 수 있습니다.

class Data(object):
    __slots__ = ['n']
    def __init__(self, n):
        self.n = n
    def __eq__(self, other):
        if not isinstance(other, Data):
            return False
        if self.n != other.n:
            return False
        return True
    def __hash__(self):
        return self.n

    myList = [ Data(1), Data(2), Data(3) ]
    Data(2) in myList  #==> True
    Data(5) in myList  #==> False

3

사전 사용을 고려하십시오.

myDict = {}

for i in range(20):
    myDict[i] = i * i

print(5 in myDict)

또는 : d = dict ((i, i * i) for i in range (20))
hughdbrown

내 질문을 설명하는 데 사용한 사소한 문제를 해결했지만 근본적인 질문을 실제로 해결하지는 못했습니다. 내가 찾고 있던 대답 (5 년 이상 전)은 목록 이해였습니다. :)
m0j0

1

또 다른 방법은 next () 함수를 사용하는 것입니다.

matched_obj = next(x for x in list if x.n == 10)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.