2013-05-09 10 views
29

Próbuję użyć rozumienia list, które porównuje obiekty ciąg, ale jeden z ciągów jest utf-8, produkt uboczny json.loads. Scenariusz:Jak mogę porównać typ Unicode z ciągiem w python?

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

Część pierwsza mojego pytania brzmi: dlaczego to zwraca Fałsz? :

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

Część druga - jak mogę porównać ze zrozumieniem listy?

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

EDIT: używam Google App Engine, który wykorzystuje Pythona 2.7

Oto bardziej kompletny przykład problemu:

#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

część 1 zwraca mi prawdę. – karthikr

+1

zwraca także True dla mnie, czy jesteś w python3? – cmd

+0

[W python3] (http://ideone.com/F3BI7d) – Eric

Odpowiedz

19

Musisz przechodzić przez niewłaściwy zestaw danych; tylko pętla bezpośrednio nad słowniku JSON załadowane, nie ma potrzeby, aby zadzwonić .keys() pierwszy:

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

Możesz użyć u"number1" uniknąć niejawne konwersje pomiędzy Unicode i bajtów ciągi:

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

Obie wersje praca grzywny:

>>> 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'] 

Należy zauważyć, że w pierwszym przykładzie, us to nie ciąg znaków UTF-8; to dane w formacie Unicode, biblioteka json już to odkodowała. Z drugiej strony ciąg znaków UTF-8 jest sekwencją zakodowanych bajtów.może chcesz przeczytać na Unicode i Python, aby zrozumieć różnicę:

On Python 2, twoje oczekiwanie, że twój test zwróci True, byłoby rect, robisz coś innego źle:

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

Jest nr potrzeba do kodowania ciągów na UTF-8, aby dokonać porównań; zamiast używać unicode literałów:

myComp = [elem for elem in json_data if elem == u"MyString"] 
3

Jestem zakładając używasz Python 3. us.encode('utf-8') == "MyString" powraca False ponieważ funkcja str.encode() jest returning a bytes object:

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

W języku Python 3 ciągi znaków to already Unicode, więc u'MyString' jest zbędny.

11

Próbujesz porównać ciąg bajtów ('MyString') z ciągiem punktów kodowych Unicode (u'MyString'). To porównanie "jabłka i pomarańcze". Niestety, Python 2 udaje w niektórych przypadkach, że to porównanie jest poprawny, a nie zawsze wraca False:

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

To do was jako projektant/programista, aby zdecydować, co prawidłowe porównanie powinno być. Oto jeden z możliwych sposobów:

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

polecam wyżej zamiast a == b.decode('UTF-8') ponieważ wszystkie u'' style łańcuchy mogą być kodowane w bajtach z UTF-8, z wyjątkiem być może w niektórych dziwnych przypadkach, ale nie wszystkie bajtowe-strings mogą być dekodowane w ten sposób w Unicode.

Ale jeśli zdecydujesz się na kodowanie UTF-8 ciągów Unicode przed porównaniem, to nie powiedzie się na coś takiego w systemie Windows: u'Em dashes\u2014are cool'.encode('UTF-8') == 'Em dashes\x97are cool'. Ale jeśli chcesz .encode('Windows-1252'), to się uda. To dlatego porównanie jabłek i pomarańczy.

+1

Dlaczego jest oczywiste, że OP używa Pythona 2? Jeśli był to Python 2, jego test zwróciłby wartość "True", ** not ** 'False'. –

+1

Wygląda na to, że powtórzyłem mu jego literówkę. Wyraźnie stwierdza, że ​​Python 2 po jego edycji, więc będę edytować również odpowiedź. – wberry

Powiązane problemy