Я получаю dict из одного "слоя" кода, на котором выполняются некоторые вычисления/модификации, прежде чем передать его на другой "слой". Исходные ключи dict и "строковые" значения unicode
, но слой, на который они передаются, принимает только str
.
Это будет часто вызвано, поэтому я хотел бы знать, каким будет самый быстрый способ конвертировать что-то вроде:
{ u'spam': u'eggs', u'foo': True, u'bar': { u'baz': 97 } }
... в:
{ 'spam': 'eggs', 'foo': True, 'bar': { 'baz': 97 } }
... принимая во внимание, что значения, отличные от "строки", должны оставаться в качестве их исходного типа.
Любые мысли?
Ответ 1
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)
, если вам нужна явная кодировка).
Если вам нужно поддерживать другие типы контейнеров, мы надеемся, что это будет очевидно, как следовать шаблону и добавлять к ним случаи.
Ответ 2
Я знаю, что опаздываю на этот:
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())
Ответ 3
Если вы хотите сделать это встроенный и не нужно рекурсивный спуск, это может работать:
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
def to_str(key, value):
if isinstance(key, unicode):
key = str(key)
if isinstance(value, unicode):
value = str(value)
return key, value
передать ключ и значение ему и добавить рекурсию к вашему коду для учета внутреннего словаря.
Ответ 5
для не-вложенного dict (так как название не упоминает этот случай, это может быть интересно для других людей)
{str(k): str(v) for k, v in my_dict.items()}
Ответ 6
Чтобы сделать все встроенным (нерекурсивным):
{str(k):(str(v) if isinstance(v, unicode) else v) for k,v in my_dict.items()}