34

我正在尝试使用比较字符串对象的列表理解,但其中一个字符串是 utf-8,它是 json.loads 的副产品。设想:

us = u'MyString' # is the utf-8 string

我的问题的第一部分是,为什么这会返回 False?:

us.encode('utf-8') == "MyString" ## False

第二部分 - 我如何在列表理解中进行比较?

myComp = [utfString for utfString in jsonLoadsObj
           if utfString.encode('utf-8') == "MyString"] #wrapped to read on S.O.

编辑:我正在使用 Google App Engine,它使用 Python 2.7

这是问题的更完整示例:

#json coming from remote server:
#response object looks like:  {"number1":"first", "number2":"second"}

data = json.loads(response)
k = data.keys()

I need something like:
myList = [item for item in k if item=="number1"]  

#### I thought this would work:
myList = [item for item in k if item.encode('utf-8')=="number1"]
4

3 回答 3

22

你一定是在循环错误的数据集;只需直接遍历 JSON 加载的字典,无需先调用.keys()

data = json.loads(response)
myList = [item for item in data if item == "number1"]  

您可能希望使用它u"number1"来避免 Unicode 和字节字符串之间的隐式转换:

data = json.loads(response)
myList = [item for item in data if item == u"number1"]  

两个版本都可以正常工作

>>> import json
>>> data = json.loads('{"number1":"first", "number2":"second"}')
>>> [item for item in data if item == "number1"]
[u'number1']
>>> [item for item in data if item == u"number1"]
[u'number1']

请注意,在您的第一个示例中,不是usUTF -8 字符串;它是 unicode 数据,图书馆已经为你解码了。另一方面,UTF-8 字符串是序列编码的字节。您可能需要阅读 Unicode 和 Python 以了解其中的区别:json

在 Python 2 上,您期望您的测试返回True正确,但您做错了其他事情:

>>> us = u'MyString'
>>> us
u'MyString'
>>> type(us)
<type 'unicode'>
>>> us.encode('utf8') == 'MyString'
True
>>> type(us.encode('utf8'))
<type 'str'>

无需将字符串编码为UTF-8 进行比较;改用 unicode 文字:

myComp = [elem for elem in json_data if elem == u"MyString"]
于 2013-05-09T21:29:53.890 回答
12

您正在尝试将一串字节 ( 'MyString') 与一串 Unicode 代码点 ( u'MyString') 进行比较。这是一个“苹果和橘子”的比较。不幸的是,Python 2 在某些情况下假装这种比较是有效的,而不是总是返回False

>>> u'MyString' == 'MyString'  # in my opinion should be False
True

作为设计师/开发人员,您可以决定正确的比较应该是什么。这是一种可能的方法:

a = u'MyString'
b = 'MyString'
a.encode('UTF-8') == b  # True

我建议使用上述方法,而不是a == b.decode('UTF-8')因为所有u''样式字符串都可以使用 UTF-8 编码为字节,但可能在某些奇怪的情况下除外,但并非所有字节字符串都可以通过这种方式解码为 Unicode。

但是,如果您选择在比较之前对 Unicode 字符串进行 UTF-8 编码,那么在 Windows 系统上这样的事情将会失败:u'Em dashes\u2014are cool'.encode('UTF-8') == 'Em dashes\x97are cool'. 但如果你.encode('Windows-1252')改为它会成功。这就是为什么它是一个苹果和橘子的比较。

于 2013-05-09T21:34:28.233 回答
3

我假设您使用的是 Python 3。us.encode('utf-8') == "MyString"返回False是因为该str.encode()函数返回一个字节对象

In [2]: us.encode('utf-8')
Out[2]: b'MyString'

在 Python 3 中,字符串已经是 Unicode了,所以u'MyString'是多余的。

于 2013-05-09T21:27:46.573 回答