2012-10-27 159 views
10

可能重复:
How to get string Objects instead Unicode ones from JSON in Python?的Python:从转换Unicode字符串的复杂字典ASCII

我有很多输入从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 
+1

如果你使用的是Python 2,那么unicode不是'str'的​​实例,而是'unicode'的实例。另外,在'list'和'dict'处理中,你做错了。 – agf

+0

对于列表案例,您不妨考虑处理任何迭代。无论如何,你可以用'ret = [convert(x)for x in input]'替换if语句的分支。另外,检查你的字典案例。 'ret'将只包含字典中最后一个键转换成的内容。 –

+0

@MichaelMior按照你所描述的方式处理任何迭代的麻烦是,并非所有的迭代器都是类似列表的。例如,字典是可迭代的,但如果'input'是一个字典,'ret = [convert for(x)in input]'显然不是我们想要的。 –

回答

23

递归好像走在这里的方式,但如果你在蟒蛇2.xx的要被检查对于unicode,不str(所述str类型表示的字节串,和unicode类型的Unicode字符的字符串;非从其他继承,它是在他们面前显示在解释用Au Unicode的类型字符串) 。

您的发布代码中还有一点语法错误(尾随的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编码,所以使用的,而不是ASCII UTF-8不能破坏任何东西而在当代表只要您处理的Unicode字符串只使用ASCII字符,该更改将不可见。但是,这种改变扩展了函数的范围,以便能够处理整个Unicode字符集中的字符串,而不仅仅是ASCII字符,如果这样的事情是必需的。

+1

+1。除了你对递归的评论:)递归对于几乎任何类型的树遍历和大多数解析问题都很有用。递归往往是“走的路”,特别是在函数式编程方面。 –

+1

@JoelCornett够了。我的评论并不意味着广泛的反递归;我可以看到递归在树遍历问题中是有意义的,其中我猜很多解析问题是一个子集。我对这个游戏非常新颖,而不是来自compsci背景,所以我还没有遇到过这种性质的问题。我所看到的递归的例子往往是毫无意义和做作的,并将其应用于迭代更清晰的情况。这是我第一次突然走了'哇,递归*真的简化了这里的事情',这对我来说很令人兴奋。 :) –

+0

谢谢,这真的很好。比问题中的任何答案都好得多,这被认为是重复的。 – Dreen