【问题标题】:Python: Convert complex dictionary of strings from Unicode to ASCII [duplicate]Python:将复杂的字符串字典从Unicode转换为ASCII [重复]
【发布时间】:2012-10-17 14:07:18
【问题描述】:

可能重复:
How to get string Objects instead Unicode ones from JSON in Python?

作为从 JSON API 调用解析的多级字典,我有很多输入。这些字符串都是 unicode,这意味着有很多 u'stuff like this'。我正在使用jq 来处理结果,需要将这些结果转换为 ASCII。

我知道我可以编写一个函数来像这样转换它:

def convert(input):
    if isinstance(input, dict):
        ret = {}
        for stuff in input:
            ret = convert(stuff)
    elif isinstance(input, list):
        ret = []
        for i in range(len(input))
            ret = convert(input[i])
    elif isinstance(input, str):
        ret = input.encode('ascii')
    elif :
        ret = input
    return ret

这是否正确?不确定。不过这不是我想问你的。

我要问的是,这是解决问题的典型暴力解决方案。一定会有更好的办法。一种更pythonic的方式。我不是算法方面的专家,但这个看起来也不是特别快。

那么有没有更好的方法呢?或者如果没有,这个功能可以改进吗...?


回答后编辑

Mark Amery's answer 是正确的,但我想发布它的修改版本。他的函数适用于 Python 2.7+,而我使用的是 2.6,因此必须对其进行转换:

def convert(input):
    if isinstance(input, dict):
        return dict((convert(key), convert(value)) for key, value in input.iteritems())
    elif isinstance(input, list):
        return [convert(element) for element in input]
    elif isinstance(input, unicode):
        return input.encode('utf-8')
    else:
        return input

【问题讨论】:

  • 如果您使用的是 Python 2,那么 unicode 不是str 的实例,而是unicode 的实例。另外,在listdict 处理中,你做错了。
  • 对于列表情况,您可能希望考虑处理任何可迭代的。在任何情况下,您都可以将 if 语句的分支替换为 ret = [convert(x) for x in input]。另外,检查你的字典大小写。 ret 将只包含字典中最后一个键转换为的任何内容。
  • @MichaelMior 以您所描述的方式处理任何可迭代对象的麻烦在于,并非所有可迭代对象都是类似列表的。例如,字典是可迭代的,但如果 input 是字典,ret = [convert(x) for x in input] 显然不是我们想要的。
  • @MarkAmery 当然。字典需要单独处理。

标签: python json algorithm unicode ascii


【解决方案1】:

递归似乎是这里的方法,但如果你在 python 2.xx 上,你想检查unicode,而不是strstr 类型代表一串字节,而unicode 键入一串 unicode 字符;两者都不是从另一个继承,在解释器中显示的是 unicode 类型的字符串,它们前面带有 au)。

您发布的代码中还有一点语法错误(结尾的 elif: 应该是 else),并且在输入是字典或列表的情况下,您不会返回相同的结构。 (在字典的情况下,您将返回最终键的转换版本;在列表的情况下,您将返回最终元素的转换版本。两者都不对!)

您还可以通过使用推导来使您的代码漂亮和 Pythonic。

那么,这是我的建议:

def convert(input):
    if isinstance(input, dict):
        return {convert(key): convert(value) for key, value in input.iteritems()}
    elif isinstance(input, list):
        return [convert(element) for element in input]
    elif isinstance(input, unicode):
        return input.encode('utf-8')
    else:
        return input

最后一件事。我将encode('ascii') 更改为encode('utf-8')。我的推理如下:任何仅包含 ASCII 字符集中字符的 unicode 字符串在以 ASCII 编码时将由与以 utf-8 编码时相同的字节字符串表示,因此使用 utf-8 而不是 ASCII 不能破坏任何东西和只要您处理的 unicode 字符串仅使用 ASCII 字符,更改将不可见。但是,此更改扩展了函数的范围,以便能够处理来自整个 unicode 字符集的字符串,而不仅仅是 ASCII 字符串,如果有必要的话。

【讨论】:

  • +1。除了你对递归的评论:) 递归对于几乎任何类型的树遍历和大多数解析问题都很有用。递归通常是“必经之路”,尤其是在函数式编程方面。
  • @JoelCornett 够公平的。我的评论并不意味着广泛的反递归。我可以看到递归在树遍历问题中是有意义的,我猜很多解析问题都是其中的一个子集。我只是这个游戏的新手,而不是来自compsci背景,所以我自己还没有遇到任何这种性质的问题。我见过的递归示例往往毫无意义且做作,并将其应用于迭代更清晰的情况。这是我第一次突然想到“哇,这里的递归真的简化了事情”,这让我很兴奋。 :)
  • 谢谢,这真的很好。比这个问题中的任何答案都要好得多,这应该是重复的。
  • 我也发布了你的旧 Python 代码的修改版本
  • 工作就像一个魅力,谢谢
猜你喜欢
  • 2012-11-27
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 2019-06-04
  • 1970-01-01
相关资源
最近更新 更多