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


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.