dict의 키와 값을`unicode`에서`str`로 변환하는 가장 빠른 방법은 무엇입니까?


81

다른 "계층"으로 전달하기 전에 일부 계산 / 수정이 수행되는 코드의 "계층"에서 dict를 받고 있습니다. 원래 dict의 키와 "문자열"값은 unicode이지만 전달되는 레이어는 str.

이것은 자주 호출 될 것이므로 다음과 같이 변환하는 가장 빠른 방법이 무엇인지 알고 싶습니다.

{ u'spam': u'eggs', u'foo': True, u'bar': { u'baz': 97 } }

...에:

{ 'spam': 'eggs', 'foo': True, 'bar': { 'baz': 97 } }

... 비 "문자열"값은 원래 유형으로 유지되어야합니다.

이견있는 사람?

답변:


150
DATA = { u'spam': u'eggs', u'foo': frozenset([u'Gah!']), u'bar': { u'baz': 97 },
         u'list': [u'list', (True, u'Maybe'), set([u'and', u'a', u'set', 1])]}

def convert(data):
    if isinstance(data, basestring):
        return str(data)
    elif isinstance(data, collections.Mapping):
        return dict(map(convert, data.iteritems()))
    elif isinstance(data, collections.Iterable):
        return type(data)(map(convert, data))
    else:
        return data

print DATA
print convert(DATA)
# Prints:
# {u'list': [u'list', (True, u'Maybe'), set([u'and', u'a', u'set', 1])], u'foo': frozenset([u'Gah!']), u'bar': {u'baz': 97}, u'spam': u'eggs'}
# {'bar': {'baz': 97}, 'foo': frozenset(['Gah!']), 'list': ['list', (True, 'Maybe'), set(['and', 'a', 'set', 1])], 'spam': 'eggs'}

가정 :

  • 컬렉션 모듈을 가져 왔으며 제공하는 추상 기본 클래스를 사용할 수 있습니다.
  • 기본 인코딩을 사용하여 변환하는 data.encode('utf-8')것이 좋습니다 ( str(data)명시적인 인코딩이 필요한 경우 보다는 사용 ).

다른 컨테이너 유형을 지원해야하는 경우 패턴을 따르고 케이스를 추가하는 방법이 분명하기를 바랍니다.


그리고 일부 값이 목록 / 세트 / 등이면 어떻게할까요?
Phillip B Oldham

@Philip : 케이스를 추가하세요. 답변이 업데이트 된 다음 컨테이너 내의 중첩 컨테이너에 대해 다시 업데이트되었습니다.
RichieHindle

1
튜플과 frozenset, Richi를 잊어 버렸습니다.
SilentGhost 2009-08-10

3
type(data)(map(convert, data))대신 왜 사용 map(convert, data)합니까?
Abbasov Alexander

4
@AbbasovAlexander : 입력 한 것과 동일한 유형을 되돌리려면 튜플이 튜플이되고 목록이 목록이되고 집합이 집합이되는 식입니다.
RichieHindle

23

나는 이것에 늦었다는 것을 안다.

def convert_keys_to_string(dictionary):
    """Recursively converts dictionary keys to strings."""
    if not isinstance(dictionary, dict):
        return dictionary
    return dict((str(k), convert_keys_to_string(v)) 
        for k, v in dictionary.items())

1
네, 이것은 올바른 방법 인 것 같습니다. 인라인 및 기타 버전은 실제로 실제 시나리오에 충분하지 않습니다. 안타깝게도이를 수행하는 신뢰할 수있는 인라인 재귀없는 방법이 없습니다. 아니면 파이썬 str (...) json 규칙을 기반으로할까요?
jayunit100

1
이것은 제가 찾던 키만 변환하는 것이 제가 가장 좋아하는 것입니다. 작은 오타 : 반환되는 dict () 인수 주위에 추가 ()가 필요합니다.
ggll 2013-07-30

이 솔루션의 유일한 문제는 키가 모든 문자열 (예 : int 유형)이 아닌 경우입니다.
MrWonderful

@ MrWonderful 그리고 그 이유는 무엇입니까? strint 를 호출하는 데 문제가 없음
Germano

@Germano : 물론 int에 대해 str ()을 호출 할 수 있지만 더 이상 int가 아닌 str ....을 얻습니다. 키의 유형 인 STR에 대한 INT, 변경 될 수 그래서 원래의 질문을 - STR에 유니 코드를 변경하는 대신.
MrWonderful

13

이 작업을 인라인으로 원하고 재귀 하강이 필요하지 않은 경우 다음과 같이 작동 할 수 있습니다.

DATA = { u'spam': u'eggs', u'foo': True, u'bar': { u'baz': 97 } }
print DATA
# "{ u'spam': u'eggs', u'foo': True, u'bar': { u'baz': 97 } }"

STRING_DATA = dict([(str(k), v) for k, v in data.items()])
print STRING_DATA
# "{ 'spam': 'eggs', 'foo': True, 'bar': { u'baz': 97 } }"

4
2.7 이상에서는 다음과 같이 단순화 할 수 있습니다.{ str(key):value for key,value in data.items() }
AnjoMan

4

중첩되지 않은 딕셔너리의 경우 (제목에 해당 사례가 언급되어 있지 않으므로 다른 사람들에게 흥미로울 수 있음)

{str(k): str(v) for k, v in my_dict.items()}

1
{STR (K) (K)에 대한 STR (V)에 my_dict.items V ()}
yardstick17

도움이 내가 내 dataframe 열 비교할 필요가 문자열로 내 열쇠를 변환
메가 마인드

3
def to_str(key, value):
    if isinstance(key, unicode):
        key = str(key)
    if isinstance(value, unicode):
        value = str(value)
    return key, value

키와 값을 전달하고 내부 사전을 설명하기 위해 코드에 재귀를 추가합니다.


2

모두 인라인 (비 재귀)으로 만들려면 :

{str(k):(str(v) if isinstance(v, unicode) else v) for k,v in my_dict.items()}

0

그냥 사용 print(*(dict.keys()))

*는 목록과 같은 컨테이너를 풀 때 사용할 수 있습니다. *에 대한 자세한 내용은 이 SO 답변을 확인하십시오 .


이 코드가 문제를 해결할 수 있지만 좋은 대답은 코드의 기능과 도움이되는 방법을 설명 해야 합니다 .
BDL

0
>>> d = {u"a": u"b", u"c": u"d"}
>>> d
{u'a': u'b', u'c': u'd'}
>>> import json
>>> import yaml
>>> d = {u"a": u"b", u"c": u"d"}
>>> yaml.safe_load(json.dumps(d))
{'a': 'b', 'c': 'd'}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.