[python] 목록에서 어떤 값과 동일한 속성을 가진 객체를 찾습니다 (조건에 부합)

개체 목록이 있습니다. 이 목록에서 속성 (또는 메소드 결과에 관계없이)이 하나 인 (첫 번째 또는 다른) 객체를 찾고 싶습니다 value.

그것을 찾는 가장 좋은 방법은 무엇입니까?

테스트 사례는 다음과 같습니다.

  class Test:
      def __init__(self, value):
          self.value = value

  import random

  value = 5

  test_list = [Test(random.randint(0,100)) for x in range(1000)]

  # that I would do in Pascal, I don't believe isn't anywhere near 'Pythonic'
  for x in test_list:
      if x.value == value:
          print "i found it!"
          break

나는 발전기를 사용한다고 생각 reduce()하지만 여전히 목록을 반복 할 것이기 때문에 아무런 차이가 없습니다.

추신 : 방정식 value은 단지 예입니다. 물론 우리는 어떤 조건에 맞는 요소를 원합니다.



답변

next((x for x in test_list if x.value == value), None)

조건과 일치하는 목록에서 첫 번째 항목을 가져오고 일치하는 None항목이 없으면 반환 합니다. 내가 선호하는 단일 표현 양식입니다.

하나,

for x in test_list:
    if x.value == value:
        print "i found it!"
        break

순진한 루프 브레이크 버전은 완벽하게 Pythonic입니다. 간결하고 명확하며 효율적입니다. 원 라이너의 동작과 일치 시키려면 :

for x in test_list:
    if x.value == value:
        print "i found it!"
        break
else:
    x = None

루프를 벗어나지 않으면 할당 None됩니다 .xbreak


답변

그것은 단지 완료를 위해 언급되지 않았기 때문에. 필터링 된 요소를 필터링하는 좋은 ol ‘필터.

기능적 프로그래밍 ftw.

####### Set Up #######
class X:

    def __init__(self, val):
        self.val = val

elem = 5

my_unfiltered_list = [X(1), X(2), X(3), X(4), X(5), X(5), X(6)]

####### Set Up #######

### Filter one liner ### filter(lambda x: condition(x), some_list)
my_filter_iter = filter(lambda x: x.val == elem, my_unfiltered_list)
### Returns a flippin' iterator at least in Python 3.5 and that's what I'm on

print(next(my_filter_iter).val)
print(next(my_filter_iter).val)
print(next(my_filter_iter).val)

### [1, 2, 3, 4, 5, 5, 6] Will Return: ###
# 5
# 5
# Traceback (most recent call last):
#   File "C:\Users\mousavin\workspace\Scripts\test.py", line 22, in <module>
#     print(next(my_filter_iter).value)
# StopIteration


# You can do that None stuff or whatever at this point, if you don't like exceptions.

나는 일반적으로 파이썬 목록에서 이해가 바람직하거나 적어도 그것이 읽은 것임을 알고 있지만 문제가 정직하지는 않습니다. 물론 파이썬은 FP 언어는 아니지만 Map / Reduce / Filter는 완벽하게 읽을 수 있으며 함수형 프로그래밍에서 가장 표준적인 표준 사용 사례입니다.

그래서 당신은 간다. 당신의 기능적 프로그래밍을 아십시오.

필터 조건 목록

이보다 더 쉬울 수는 없습니다.

next(filter(lambda x: x.val == value,  my_unfiltered_list)) # Optionally: next(..., None) or some other default value to prevent Exceptions


답변

간단한 예 : 다음 배열이 있습니다.

li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]

이제 배열에서 id가 1 인 객체를 찾고자합니다.

  1. next목록 이해와 함께 사용 방법
next(x for x in li if x["id"] == 1 )
  1. 목록 이해를 사용하고 첫 번째 항목을 반환
[x for x in li if x["id"] == 1 ][0]
  1. 커스텀 기능
def find(arr , id):
    for x in arr:
        if x["id"] == id:
            return x
find(li , 1)

위의 모든 방법을 출력하십시오. {'id': 1, 'name': 'ronaldo'}


답변

방금 비슷한 문제가 발생하여 목록의 객체가 요구 사항을 충족하지 않는 경우에 대한 작은 최적화를 고안했습니다. (사용 사례의 경우 주요 성능이 향상되었습니다.)

test_list 목록과 함께 필터링해야 할 목록의 값으로 구성된 추가 test_value_set 세트를 유지합니다. 그래서 여기서 agf 솔루션의 else 부분은 매우 빠릅니다.


답변

이런 식으로 할 수 있습니다

dict = [{
   "id": 1,
   "name": "Doom Hammer"
 },
 {
    "id": 2,
    "name": "Rings ov Saturn"
 }
]

for x in dict:
  if x["id"] == 2:
    print(x["name"])

그것이 긴 객체 배열에서 객체를 찾는 데 사용하는 것입니다.


답변

클래스 및 사용 연산자에 __eq__대한 메소드를 통해 풍부한 비교를 구현할 수도 있습니다 . 이것이 최상의 독립 실행 형인지 확실하지 않지만 다른 곳을 기준으로 인스턴스 를 비교 해야하는 경우 유용 할 수 있습니다.TestinTestvalue

class Test:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        """To implement 'in' operator"""
        # Comparing with int (assuming "value" is int)
        if isinstance(other, int):
            return self.value == other
        # Comparing with another Test object
        elif isinstance(other, Test):
            return self.value == other.value

import random

value = 5

test_list = [Test(random.randint(0,100)) for x in range(1000)]

if value in test_list:
    print "i found it"


답변

아래 코드에서 xGen은 익명 생성기 표현식이고 yFilt는 필터 객체입니다. xGen의 경우 목록이 소진 될 때 StopIteration을 발생시키지 않고 추가 None 매개 변수가 반환됩니다.

arr =((10,0), (11,1), (12,2), (13,2), (14,3))

value = 2
xGen = (x for x in arr if x[1] == value)
yFilt = filter(lambda x: x[1] == value, arr)
print(type(xGen))
print(type(yFilt))

for i in range(1,4):
    print('xGen: pass=',i,' result=',next(xGen,None))
    print('yFilt: pass=',i,' result=',next(yFilt))

산출:

<class 'generator'>
<class 'filter'>
xGen: pass= 1  result= (12, 2)
yFilt: pass= 1  result= (12, 2)
xGen: pass= 2  result= (13, 2)
yFilt: pass= 2  result= (13, 2)
xGen: pass= 3  result= None
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    print('yFilt: pass=',i,' result=',next(yFilt))
StopIteration