【问题标题】:Fastest way to convert a dict's keys & values from `unicode` to `str`?将字典键和值从 `unicode` 转换为 `string` 的最快方法?
【发布时间】:2020-08-04 11:20:48
【问题描述】:

我从一个代码“层”接收到一个字典,在将其传递到另一个“层”之前,会在该代码上执行一些计算/修改。原始字典的键和“字符串”值是unicode,但它们被传递到的层只接受str

这将被经常调用,所以我想知道转换以下内容的最快方法是什么:

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

...到:

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

...记住非“字符串”值需要保持其原始类型。

有什么想法吗?

【问题讨论】:

    标签: python casting types


    【解决方案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))。

    如果您需要支持其他容器类型,希望很明显如何遵循该模式并为它们添加案例。

    【讨论】:

    • 如果某些值是列表/集合/等,该怎么办?
    • 你忘记了元组和frozenset,Richi
    • 你为什么用type(data)(map(convert, data))而不是map(convert, data)
    • @AbbasovAlexander:这样你就可以得到你输入的相同类型——一个元组变成一个元组,一个列表变成一个列表,一个集合变成一个集合,等等。
    • @Moberg:只有当你的数据结构嵌套了数百层时。
    【解决方案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())
    

    【讨论】:

    • 是的,这似乎是正确的做法,内联和其他版本确实不足以满足现实世界的场景。太糟糕了,没有可靠的内联无递归方式来实现这一点。或者也许有基于 python str(...) 的 json 约定?
    • 这是我最喜欢的,只转换密钥,这是我一直在寻找的。小错字:您需要在返回的 dict() 参数周围加上一个 ()。
    • 这个解决方案的唯一问题是如果你的键不是所有的字符串(即 int 类型)
    • @MrWonderful 为什么会这样?我在 int 上调用 str 看不到任何问题
    • @Germano :当然,您可以在 int 上调用 str(),但您会得到一个 str...。不再是 int。因此,键的类型将从 int 更改为 str,这比将 unicode 更改为 str 更多 - 原始问题。
    【解决方案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 } }"
    

    【讨论】:

    • 对于 2.7 及更高版本,这可以简化如下:{ str(key):value for key,value in data.items() }
    【解决方案4】:

    对于一个非嵌套的字典(因为标题没有提到这种情况,它可能对其他人来说很有趣)

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

    【讨论】:

    • {str(k): str(v) for k, v in my_dict.items()}
    • 这有助于将我的键转换为我需要与我的数据框列进行比较的字符串
    【解决方案5】:
    def to_str(key, value):
        if isinstance(key, unicode):
            key = str(key)
        if isinstance(value, unicode):
            value = str(value)
        return key, value
    

    将键和值传递给它,并在代码中添加递归以说明内部字典。

    【讨论】:

      【解决方案6】:

      使其全部内联(非递归):

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

      【讨论】:

        【解决方案7】:
        >>> 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'}
        

        【讨论】:

          【解决方案8】:

          只需使用print(*(dict.keys()))

          * 可用于拆箱容器,例如列表。有关 * 的更多信息,请查看this SO answer

          【讨论】:

          • 虽然这段代码可能会解决问题,但一个好的答案应该解释代码的什么以及它如何提供帮助。
          猜你喜欢
          • 2010-11-18
          • 2016-10-04
          • 2016-01-13
          • 2016-09-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多