파이썬 사전에서 값에 대한 매핑


243

사전을 감안할 때 { k1: v1, k2: v2 ... }내가 얻을 싶어 { k1: f(v1), k2: f(v2) ... }내가 함수를 통과 제공을 f.

그러한 내장 기능이 있습니까? 아니면해야합니까

dict([(k, f(v)) for (k, v) in my_dictionary.iteritems()])

이상적으로 나는 단지 쓸 것입니다

my_dictionary.map_values(f)

또는

my_dictionary.mutate_values_with(f)

즉, 원래 사전이 변경되거나 사본이 생성되면 중요하지 않습니다.


2
예제를 작성하는 더 좋은 방법은 dict((k, f(v)) for k, v in mydict.iteritems())즉, 대괄호없이 생성기를 통해 중간 목록을 생성하지 못하게하는 것입니다.
bereal

답변:


354

그러한 기능은 없습니다. 가장 쉬운 방법은 dict comprehension을 사용하는 것입니다.

my_dictionary = {k: f(v) for k, v in my_dictionary.items()}

Python 2.7에서는 메모리를 저장 .iteritems()하는 대신 메소드를 사용하십시오 .items(). dict comprehension 구문은 Python 2.7까지 도입되지 않았습니다.

목록에는 그러한 방법이 없습니다. 리스트 이해력이나 map()기능 을 사용해야 합니다.

map()따라서이 함수를 사용 하여 받아쓰기를 처리 할 수도 있습니다 .

my_dictionary = dict(map(lambda kv: (kv[0], f(kv[1])), my_dictionary.iteritems()))

그러나 그것은 실제로 읽을 수있는 것은 아닙니다.


5
+1 : 이것도 내가 할 것입니다. dict(zip(a, map(f, a.values())))조금 짧아 지지만, 나는 그것이하는 일에 대해 생각해야하며, 그래도 dict이 변경되지 않으면 키와 값이 동일한 순서로 반복된다는 것을 상기해야합니다. 나는 dictcomp가 무엇을하고 있는지 전혀 생각할 필요가 없으므로 정답입니다.
DSM

2
@chiborg : 모든 키-값 쌍을 한 번에 조회하는 것이 아니라 이제 number-of-keys x my_dictionary.__getitem__호출을 사용하기 때문입니다.
Martijn Pieters

1
이후 있습니다 PEP3113 (파이썬 3.x를 구현) 튜플 매개 변수는 더 이상 지원되지 않습니다이 : lambda (k,v): (k, f(v))같은 것으로 다시 작성하는 것입니다lambda k_v: (k_v[0], f(k_v[1]))
normanius

1
파라미터 언 패킹이 왜 해결 되었습니까? 그것은 어떻게 개선 입니까?
javadba

3
FP 언어에서 나온 파이썬은 엄청나게 어색해 보일 것입니다.
juanchito


21

새로운 사전을 작성하는 대신이 작업을 제자리에서 수행 할 수 있습니다 (사전이 필요없는 경우).

def mutate_dict(f,d):
    for k, v in d.iteritems():
        d[k] = f(v)

my_dictionary = {'a':1, 'b':2}
mutate_dict(lambda x: x+1, my_dictionary)

다음을 my_dictionary포함하는 결과 :

{'a': 2, 'b': 3}

1
멋지다, 당신은 아마 당신이 dict을 다시 작성하도록 명백하게하기 위해 이름 mapdict을 바꾸 mutate_values_with거나 무언가를 바꿔야 할 것입니다! :)
Tarrasch

2
zip(d.keys(), d.values())대신에 더 많은 버전에 대한 작품iteritems()
ytpillai

1
@ytpillai 'zip'또는 이해력은 제 위치의 값을 변경하지 않고 사본을 만듭니다. 이것은 내 대답의 목적입니다. 수락 된 답변은 사본이 정상일 때 가장 적합합니다.
gens

1
사과합니다, 아이템 방법을 사용하고 싶었습니다. 그러나 다른 개선도 가능합니다 (비 Python 2.7 사용자의 경우){k:f(v) for k,v in iter(d.items())}
ytpillai

1
반복자를 만들어 공간을 절약합니다
ytpillai


4

내 원래의 대답은 ( defaultdict 공장의 액세스 키에 대한 솔루션 으로이 문제를 해결하려고 노력하면서) 요점을 놓쳤지만 현재 질문에 대한 실제 솔루션을 제안하기 위해 재 작업했습니다.

여기있어:

class walkableDict(dict):
  def walk(self, callback):
    try:
      for key in self:
        self[key] = callback(self[key])
    except TypeError:
      return False
    return True

용법:

>>> d = walkableDict({ k1: v1, k2: v2 ... })
>>> d.walk(f)

아이디어는 원하는 기능을 제공하기 위해 원래 dict을 서브 클래 싱하는 것입니다. 모든 값에 대해 함수를 "매핑"합니다.

장점은이 사전을 사용하여 원본 데이터를 마치 마치 dict콜백으로 요청시 데이터를 변환 하는 것처럼 원래 데이터를 저장하는 데 사용할 수 있다는 것 입니다.

물론 클래스와 함수의 이름을 원하는대로 자유롭게 지정할 수 있습니다 (이 답변에서 선택한 이름은 PHP의 array_walk()함수에서 영감을 얻었습니다 ).

참고 : 둘 다 try- except블록이나 return문이 기능을위한 필수, 그들은 PHP의 더 모방 행동에있다 array_walk.


1
__missing__전달 된 팩토리 메소드가 원점 dict을 대체로 대체 방법으로 사용하지 않으면 예제 사용법의 일부가 아니기 때문에 변환하려는 기존 키에 대해 메소드가 호출되지 않기 때문에 OP 질문을 해결 하지 못합니다. 나는 이것이 당면한 문제에 대한 불만족스러운 답변이라고 생각합니다.
Kaos

기존 키는 무엇입니까?
7heo.tk

OP에서 : Given a dictionary { k1: v1, k2: v2 ... } .... 즉, 당신은 이미 dict시작했습니다 ..
Kaos

우리 둘 다 옳다고 말하고 싶습니다. 하지만 우리 둘 다 틀렸다고 믿습니다. 당신은 내 대답이 그 질문에 대답하지 않는다는 점에서 옳습니다. 그러나 당신이 부르는 이유가 아닙니다. 나는 단순히 요점을 놓치고 {v1: f(v1), v2: f(v2), ...}주어진 을 얻을 수있는 방법을 [v1, v2, ...]주었고 dict 을 얻지 못했습니다. 나는 그것을 수정하기 위해 대답을 편집 할 것입니다.
7heo.tk

2

람다 내부에서 색인을 생성하지 않으려면 다음과 같이하십시오.

rval = dict(map(lambda kv : (kv[0], ' '.join(kv[1])), rval.iteritems()))

당신은 또한 할 수 있습니다 :

rval = dict(map(lambda(k,v) : (k, ' '.join(v)), rval.iteritems()))

그것은 두 번째 예제에서 2- 튜플 자체의 영리한 조작입니다. 그러나 파이썬 3에서는 더 이상 지원되지 않는 람다 내에서 자동 튜플 압축 풀기를 사용합니다 lambda(k,v). 따라서 작동하지 않습니다. 참조 stackoverflow.com/questions/21892989/...
조나단 Komar

0

이 유스 케이스에 합류했습니다. 나는 gens 's answer을 구현 하여 dicts 값을 처리하기위한 재귀 적 접근 방식을 추가했습니다.

def mutate_dict_in_place(f, d):
    for k, v in d.iteritems():
        if isinstance(v, dict):
            mutate_dict_in_place(f, v)
        else:
            d[k] = f(v)

# Exemple handy usage
def utf8_everywhere(d):
    mutate_dict_in_place((
        lambda value:
            value.decode('utf-8')
            if isinstance(value, bytes)
            else value
        ),
        d
    )

my_dict = {'a': b'byte1', 'b': {'c': b'byte2', 'd': b'byte3'}}
utf8_everywhere(my_dict)
print(my_dict)

파이썬 2에서 문자열을 바이트로 인코딩하는 json 또는 yaml 파일을 처리 할 때 유용 할 수 있습니다

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