주어진 키가 사전에 이미 있는지 확인하고 증가시킵니다.


294

사전이 주어지면 해당 사전의 주어진 키가 이미 아닌 값으로 설정되었는지 어떻게 알 수 있습니까?

즉, 나는 이것을하고 싶다 :

my_dict = {}

if (my_dict[key] != None):
  my_dict[key] = 1
else:
  my_dict[key] += 1

즉, 이미 값이 있으면 값을 늘리거나 그렇지 않으면 1로 설정하고 싶습니다.


11
작은 코드 nitpick : 코드는 이미 존재하는 경우 my_dict [key]를 1로 설정하고 존재하지 않으면 증가시킵니다. 나는 당신이 ==가 아니라! =를 원한다고 생각합니다.
— QuantumFool

답변:


331

찾고 있습니다 collections.defaultdict(Python 2.5 이상에서 사용 가능). 이

from collections import defaultdict

my_dict = defaultdict(int)
my_dict[key] += 1

당신이 원하는 것을 할 것입니다.

일반 파이썬 dict의 경우 주어진 키에 대한 값이 없으면 dict에 액세스 할 때 얻을 수 없습니다 . 따라서 코드 대신 일반을 사용 하려면NoneKeyErrordict

if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1

8
그의 예제에 따르면 "defaultdict (lambda : 0)"을 설정하고 "if"절 전체를 건너 뛰는 것으로 충분합니다.
— Deestan

이것은 작동하지만 키와 값을 혼동합니다 (읽기가 다소 이상합니다). 'some_value'는 'some_key'여야합니다.
— mikemaccana

@nailer : 고마워요. 질문에 변수 이름이기 때문에 처음에는 'some_value'를 사용했지만 지금은 더 명확하다는 데 동의합니다.
— dF.

20
... 또는 정기적 dict으로 할 수 있습니다 my_dict[key] = my_dict.get(key, 0) + 1.
— minmaxavg 2018 년

이것을 중첩 사전으로 확장하는 방법은 무엇입니까? dict [key1] [key2] + = 1?
— Pablo Ruiz Ruiz

300

한 줄의 코드 로이 작업을 선호합니다.

my_dict = {}

my_dict [some_key] = my_dict.get (some_key, 0) + 1

사전에는 get이라는 함수가 있습니다.이 함수에는 원하는 키와 존재하지 않는 경우 기본값 인 두 개의 매개 변수가 사용됩니다. 키 가이 한 줄의 코드에 존재하지 않는 경우를 처리하려는 경우에만이 방법을 기본값으로 지정하는 것이 좋습니다.


1
@AndrewWilkinson 내 나쁜. 내가해야 할만 큼 당신의 대답을 철저히 읽지 못했습니다.
— masaers

59

나는 개인적으로 사용하는 것을 좋아한다 setdefault()

my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1

setdefault굉장하다. 값이 이미 설정된 경우 값을 변경하지 않습니다 some_key. 예를 들어 d={1:2}; d.setdefault(1, 0)의 값을 방해하지 않습니다 d[1].
— wsaleem

49

그 key in dict관용구 가 필요합니다 .

if key in my_dict and not (my_dict[key] is None):
  # do something
else:
  # do something else

그러나 defaultdict(dF가 제안한대로) 사용을 고려해야 합니다.


1
적어도 2.6에서는 has_key ()가 d의 키를 위해 사용되지 않습니다. 2.5에서도 이런 식으로 생각합니다.
— David Locke

하나를 쓸 수 있습니다 my_dict[key] is not None(적어도 IMHO) 명확하다,
— brandizzi가

@brandizzi-동의합니다.if key in my_dict and my_dict[key]:
— Rob Grant

18

" 그 dict의 주어진 색인이 이미 None이 아닌 값으로 설정되어 있는지 어떻게 알 수 있습니까?"라는 질문에 대답하려면 다음 을 선호합니다.

try:
  nonNone = my_dict[key] is not None
except KeyError:
  nonNone = False

이것은 이미 호출 된 EAFP 개념 (용서를 요청한 후 허가하기가 더 쉬움)을 준수합니다. 또한 key in my_dict and my_dict[key] is not None조회 비용이 비싸면 흥미로운 점에서와 같이 사전에서 중복 키 조회를 피합니다 .

실제 문제 가 발생 하면 int가 있으면 int를 늘리거나 그렇지 않으면 기본값으로 설정하십시오.

my_dict[key] = my_dict.get(key, default) + 1

앤드류 윌킨슨의 대답 에서처럼.

사전에 수정 가능한 객체를 저장하는 경우 세 번째 해결책이 있습니다. 이에 대한 일반적인 예는 키의 요소 목록을 저장하는 멀티 맵 입니다. 이 경우 다음을 사용할 수 있습니다.

my_dict.setdefault(key, []).append(item)

사전에 키 값이 존재하지 않으면 setdefault 메소드는이를 setdefault의 두 번째 매개 변수로 설정합니다. 표준 my_dict [key]처럼 동작하며 키 값 (새로 설정 한 값일 수 있음)을 반환합니다.


실제로 파이썬처럼 보이는 것은 (나와 같은 외부인에게) 어떤 질문이라도 적어도 3 개의 유효한 답변을 가지고 있다는 것입니다.
— davka

@ davka : 글쎄, 세 가지 사용 사례는 거의 동일하지만 다릅니다 .a) 사전에 None이 아닌 요소가 있는지 확인 b) 사전에서 값을 검색하거나 값이 존재하지 않으면 기본값을 사용 c) 사전에서 값을 검색하고 값이 아직 없으면 기본값을 저장합니다.
— nd.

나는 알고있다 :) 이것은 비평이 아니다, 나는
— 단지이

@ryeguy의 답변에 대한 주석에서 Stuart Woodward는 "언어에서의 예외 처리 오버 헤드는 항상 항목이 사전에 있는지 여부를 결정하는 해시 테이블 조회보다 큰 순서입니다"라고 말합니다. 또한 사전에서 중복 키 조회를 피합니다 ... 조회 비용이 비싼 경우 "-예외 처리가 이중 키 조회보다 빠르거나 느린 위치를 측정하는 사람이 있습니까?
— Michael Firth

1
@MichaelFirth 나는 파이썬의 예외 오버 헤드에 대해 서두르는 검색을 수행 했습니다 : stackoverflow.com/questions/2522005/… 그것은 느리지 만 많이는 아닙니다. 예외 를 던지는 높은 수준의 개념은 다른 언어로 매우 다르게 처리되므로 장단점을 일반화 할 수 없습니다. 따라서 "예외에는 10 배의 오버 헤드가 있습니다"는 Java에는 맞지만 Python (또는 Swift 또는 기타)에는 적합하지 않습니다.
— nd.

13

cgoldberg와 동의 함. 내가하는 방법 :

try:
    dict[key] += 1
except KeyError:
    dict[key] = 1

따라서 위와 같이하거나 다른 사람들이 제안한대로 기본 dict를 사용하십시오. if 문을 사용하지 마십시오. 그것은 파이썬이 아닙니다.


8
if 문은 어떻게 파이썬이 아닌가?
— Adam Parkin

2
파이썬의 EAFP가 최선의 방법이 아닌 경우라고 생각합니다. 위의 예는 코드가 중복되었습니다. 일일 우리가 무엇을 원하는 경우 +=2또는 -=1? 두 줄을 모두 변경해야합니다. 지금은 사소한 일처럼 보일지 모르지만, 당신을 물기 위해 돌아올 수있는 바보 같은 작은 사소한 버그입니다.
— Cam Jackson

3
이것은 멋지게 보이고 잘 작동하지만 언어에서 예외 처리의 오버 헤드는 항상 항목이 사전에 있는지 여부를 결정하는 해시 테이블 조회보다 큰 순서라고 생각하기 때문에 일반적으로 이와 같이하지 마십시오.
— 스튜어트 우드워드

11

많은 답변에서 볼 수 있듯이 몇 가지 솔루션이 있습니다. has_key () 메소드 인 LBYL의 한 인스턴스 (도약하기 전에 살펴보기)는 아직 언급되지 않았습니다.

my_dict = {}

def add (key):
    if my_dict.has_key(key):
        my_dict[key] += 1
    else:
        my_dict[key] = 1

if __name__ == '__main__':
    add("foo")
    add("bar")
    add("foo")
    print my_dict

6
has_key ()는 'in'연산자보다 느리고 읽기 어렵습니다.
— Abgan

9
... 그리고 그것은 파이썬 2.6에서 더 이상 사용되지
— 않고

7

당신이 그것을 시도하는 방법은 당신이 가치를 높이기 전에 조건을 확인하기 때문에 LBYL (도약 전에 봐라)이라고합니다.

다른 방법은 EAFP (용서를 요청한 후 허가를 받기가 더 쉽다)라고합니다. 이 경우 작업을 시도하면됩니다 (값 증가). 실패하면 예외를 포착하고 값을 1로 설정하십시오. 이것은 약간 더 파이썬적인 방법입니다 (IMO).

http://mail.python.org/pipermail/python-list/2003-May/205182.html


5

조금 늦었지만 이것은 효과가 있습니다.

my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1

와우, 자바 프로그래머로서, 이것은 꽤 미친듯한 구조입니다. 이상한 순서의 삼항 연산자처럼 보입니까?
— forresthopkinsa

5

이것은 질문에 직접 대답하지는 않지만 collections.Counter 의 기능을 원할 것 같습니다 .

from collections import Counter

to_count = ["foo", "foo", "bar", "baz", "foo", "bar"]

count = Counter(to_count)

print(count)

print("acts just like the desired dictionary:")
print("bar occurs {} times".format(count["bar"]))

print("any item that does not occur in the list is set to 0:")
print("dog occurs {} times".format(count["dog"]))

print("can iterate over items from most frequent to least:")
for item, times in count.most_common():
    print("{} occurs {} times".format(item, times))

결과적으로 출력

Counter({'foo': 3, 'bar': 2, 'baz': 1})
acts just like the desired dictionary:
bar occurs 2 times
any item that does not occur in the list is set to 0:
dog occurs 0 times
can iterate over items from most frequent to least:
foo occurs 3 times
bar occurs 2 times
baz occurs 1 times

카운터는 defaultdict(int)일부 추가 기능 과 마찬가지로 작동하므로 정수를 다룰 때 완벽하게 작동하지만 관련 동작을 표시하지 않습니다.
— Tadhg McDonald-Jensen

4

최근 에이 문제를 해결하기 위해 생각해 낸 하나의 라이너가 있습니다. setdefault 사전 방법을 기반으로합니다 .

my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1

0

나는 그것을 찾고 있었고, 웹에서 그것을 찾지 못했고 Try / Error로 운을 시험해 보았습니다.

my_dict = {}

if my_dict.__contains__(some_key):
  my_dict[some_key] += 1
else:
  my_dict[some_key] = 1

1
__contains__프로덕션 코드에서는 사용하지 않아야 합니다. btw. __contains__를 사용하는 것과 같습니다 is.
— user1767754

1
my_dict.__contains__(some_key)행 equivelent 인 some_key in my_dict, 과부하 인 in운전자는 없다is
— Tadhg 맥도날드-젠슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.