2013-05-09 82 views
29

我想使用比較字符串對象的列表理解,但其中一個字符串是utf-8,json.loads的副產品。場景:我如何比較unicode類型與python中的字符串?

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. 

編輯:我使用谷歌應用程序引擎,它使用Python 2.7

這裏的問題的一個更完整的例子:我假設你正在使用Python

#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"] 
+1

第1部分回報給我。 – karthikr 2013-05-09 21:23:25

+1

對我來說也是True,你在python3嗎? – cmd 2013-05-09 21:23:58

+0

[在python3](http://ideone.com/F3BI7d) – Eric 2013-05-09 21:31:24

回答

19

您必須循環訪問錯誤的數據集;只是循環直接通過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'] 

注意,在你的第一個例子,us不是一個UTF-8字符串;它是unicode數據,json庫已經爲你解碼。另一方面,UTF-8字符串是編碼字節的序列。您可能需要有關Unicode和Python閱讀了理解上的差異:由Joel Spolsky的

在Python 2,你的期望是你的測試返回True將是cor矩形,你正在做別的錯誤:

>>> 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"] 
3

3. us.encode('utf-8') == "MyString"返回False因爲str.encode()功能是returning a bytes object

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

在Python 3中,字符串是already Unicode,所以u'MyString'是多餘的。

11

您正在嘗試比較的Unicode代碼點的字符串(u'MyString')字節('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')反而會成功。這就是爲什麼這是一個蘋果和橙子的比較。

+1

爲什麼OP顯然使用Python 2?如果是Python 2,他的測試會返回True,**而不是** False。 – 2013-05-09 21:39:29

+1

看起來我重複了他的錯字。他在編輯之後明確指出了Python 2,所以我也會編輯我的答案。 – wberry 2013-05-09 21:42:52