임의의 조건 함수에 따라 사전을 필터링하는 방법은 무엇입니까?


212

포인트 사전이 있습니다.

>>> points={'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)}

x와 y 값이 5보다 작은 모든 점, 즉 'a', 'b'및 'd'와 같은 새 사전을 만들고 싶습니다.

에 따르면 각 사전에는 튜플 items()목록을 반환하는 함수 가 있습니다 (key, pair).

>>> points.items()
[('a', (3, 4)), ('c', (5, 5)), ('b', (1, 2)), ('d', (3, 3))]

그래서 나는 이것을 썼다 :

>>> for item in [i for i in points.items() if i[1][0]<5 and i[1][1]<5]:
...     points_small[item[0]]=item[1]
...
>>> points_small
{'a': (3, 4), 'b': (1, 2), 'd': (3, 3)}

더 우아한 방법이 있습니까? 파이썬이 매우 멋진 dictionary.filter(f)기능 을 가질 것으로 기대했습니다 ...


답변:


427

오늘날 Python 2.7 이상에서는 dict comprehension을 사용할 수 있습니다.

{k: v for k, v in points.iteritems() if v[0] < 5 and v[1] < 5}

그리고 파이썬 3에서 :

{k: v for k, v in points.items() if v[0] < 5 and v[1] < 5}

15
공감! 이것은 Martellis보다 일반적인 접근 방식보다 2 배 이상 빠릅니다. 뷰도 사용할 수 있습니다 (예를 들어 iteitems와 같이 dict 항목의 사본이 아님). 5}
dorvak

5
그리고 함수 호출 dict ()가 생성자 / 리터럴 구문 {} doughellmann.com/2012/11/…
dorvak

1
iteritems파이썬 3에서 제거 되었다는 것을 명심하십시오 items. 그러나 대신 사용할 수 있습니다 . iteritems이전 버전에서 작동하는 방식으로 작동합니다.
Elias Zamaria

1
@Datanovice 나는 할 수 있다고 확신한다. 더 유용한 답변을 얻을 수있을만큼 상세하게 새 질문을 열 수도 있습니다.)
Thomas

1
한 사람은 대답이 제한되어있는 질문을 열었으므로 더 잘 이해하기 위해 가능한 한 많은 질문을 읽었습니다. 하나는 더 많은 지식을 가진 사람을 보았으므로 계속 두뇌를 선택했습니다.) 내 Q : stackoverflow.com/questions/50104127/…
Datanovice

110
dict((k, v) for k, v in points.items() if all(x < 5 for x in v))

당신은 전화를 선택할 수 .iteritems()대신 .items()파이썬 2 인 경우와 points있을 수 많은 항목을.

all(x < 5 for x in v)각 점이 항상 2D 만임을 확신하면 과잉 일 수 있지만 (이 경우 and)로 동일한 구속 조건을 나타낼 수는 있지만 잘 작동합니다 .-).


21
points_small = dict(filter(lambda (a,(b,c)): b<5 and c < 5, points.items()))

1
파이썬 2에서는 items () 대신
iteritems

2
points_small = 딕셔너리 (필터 (람다 (a, (b, c)) : B <5 및 C <5 points.items ())) 파이썬 3.5에서,이 에러를 반환 ^ 구문 에러 잘못된 구문 '
Mevin 바부

나는 그것이 파이썬 3에서 지원되지 않는 생각
matanster

15
>>> points = {'a': (3, 4), 'c': (5, 5), 'b': (1, 2), 'd': (3, 3)}
>>> dict(filter(lambda x: (x[1][0], x[1][1]) < (5, 5), points.items()))

{'a': (3, 4), 'b': (1, 2), 'd': (3, 3)}

3
대단해! 람다는 더 이상 튜플 인수를 풀 수 없으므로 Py3임을 언급 할 가치가 있습니다 ( PEP 3113 참조 )
Ciprian Tomoiagă

사전 식으로 튜플을 비교하면 OP가 필요하지 않습니다. 귀하의 경우, 포인트 (3, 10)는 테스트를 통과합니다 : (3, 10) < (5, 5)is True, 그러나 잘못되었습니다 ( y5보다 작아야 함).
dmitry_romanov 2016 년

9
dict((k, v) for (k, v) in points.iteritems() if v[0] < 5 and v[1] < 5)

7

Alex Martelli의 대답은 분명히이 작업을 수행하는 가장 우아한 방법이라고 생각하지만 dictionary.filter(f)파이썬 방식 으로 슈퍼 멋진 방법에 대한 귀하의 요구를 충족시키는 방법을 추가하고 싶었습니다 .

class FilterDict(dict):
    def __init__(self, input_dict):
        for key, value in input_dict.iteritems():
            self[key] = value
    def filter(self, criteria):
        for key, value in self.items():
            if (criteria(value)):
                self.pop(key)

my_dict = FilterDict( {'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)} )
my_dict.filter(lambda x: x[0] < 5 and x[1] < 5)

기본적으로 우리는에서 상속 dict하지만 필터 메소드를 추가 하는 클래스를 만듭니다 . 파괴적으로 반복 .items()하는 .iteritems()동안 사용 하면 예외가 발생하기 때문에 필터링 에 사용해야 합니다 .


+1 감사합니다. 우아한 코드입니다. 나는 그것이 표준 사전의 일부라고 생각합니다.
Adam Matan

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.