Самый быстрый способ преобразовать ключи и значения в файле dict из `unicode` в` str`? - PullRequest
75 голосов
/ 10 августа 2009

Я получаю подсказку от одного «слоя» кода, на котором выполняются некоторые вычисления / модификации перед передачей его на другой «слой». Ключи и «строковые» значения исходного дикта имеют значение unicode, но слой, на который они передаются, принимает только str.

Это будет называться часто, поэтому я хотел бы знать, какой бы самый быстрый способ конвертировать что-то вроде:

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

... чтобы:

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

... с учетом того, что не "строковые" значения должны оставаться в качестве их исходного типа.

Есть мысли?

Ответы [ 6 ]

145 голосов
/ 10 августа 2009
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), если вам нужна явная кодировка).

Если вам нужно поддерживать другие типы контейнеров, надеюсь, очевидно, как следовать шаблону и добавлять к ним регистры.

23 голосов
/ 11 августа 2011

Я знаю, что опаздываю:

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())
12 голосов
/ 18 июля 2011

Если вы хотите сделать это inline и не нуждаетесь в рекурсивном спуске, это может сработать:

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 } }"
3 голосов
/ 20 июля 2016

для не вложенного диктанта (поскольку в названии не упоминается этот случай, это может быть интересно для других людей)

{str(k): str(v) for k, v in my_dict.items()}
3 голосов
/ 10 августа 2009
def to_str(key, value):
    if isinstance(key, unicode):
        key = str(key)
    if isinstance(value, unicode):
        value = str(value)
    return key, value

передать ему ключ и значение и добавить рекурсию в свой код для учета внутреннего словаря.

2 голосов
/ 04 апреля 2017

Чтобы все это было встроено (не рекурсивно):

{str(k):(str(v) if isinstance(v, unicode) else v) for k,v in my_dict.items()}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...