将字典的键值从 `unicode` 转换为 `str` 的最快方法是什么?

83 投票
8 回答
110733 浏览
提问于 2025-04-15 13:30

我从一段代码中得到一个字典(dict),在对它进行一些计算或修改后,再把它传递给另一段代码。这个字典里的键和“字符串”值是unicode类型的,但接收它的那一层代码只接受str类型。

这个过程会被频繁调用,所以我想知道,最快的方式是什么,把类似下面的内容:

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

转换成:

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

需要注意的是,字典里非“字符串”的值要保持原来的类型。

有什么想法吗?

8 个回答

12

如果你想要直接在一行里完成这个,而且不需要递归下降的话,这样做可能会有效:

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 } }"
25

我知道我来得有点晚:

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())
156
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'}

假设:

  • 你已经导入了collections模块,并且可以使用它提供的抽象基类。
  • 你愿意使用默认的编码方式进行转换(如果需要明确的编码,使用 data.encode('utf-8') 而不是 str(data))。

如果你需要支持其他类型的容器,希望你能很容易地理解如何遵循这个模式并为它们添加相应的处理。

撰写回答