2013-05-09 6 views
29

文字列オブジェクトを比較するリスト内包を使用しようとしていますが、文字列の1つはjson.loadsの副産物であるutf-8です。シナリオ:ユニコードタイプをPythonの文字列と比較するにはどうすればよいですか?

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

私の質問の第1部は、なぜこのFalseを返しますか? :

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

パート2 - リスト内でどのように比較できますか?

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

編集:私は、Python 2.7

を使用してGoogle App Engineのを、使用していますがここでは、問題のより完全な例です:

#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

+1

も私のためにTrueを返します、あなたはpython3ですか? – cmd

+0

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

答えて

19

間違ったデータセットをルーピングする必要があります。直接JSON-ロード辞書を超えるだけのループは、最初.keys()を呼び出す必要はありません。

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

あなたはUnicodeとバイト文字列間の暗黙的な変換を避けるためにu"number1"を使用することもできます。

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文字列です。それはユニコードのデータで、jsonライブラリはすでにあなたのためにそれをデコードしています。一方、UTF-8ストリングは、シーケンスでコード化されたバイトです。あなたは違いを理解するために、UnicodeとPythonの上に読むことをお勧めします:ジョエル・スポルスキで

オンPython 2、あなたのテストがTrueを返してくれると期待しています。 RECTは、あなたが間違った何かをやっている:

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

比較を行うためにUTF-8に文字列をエンコードするなし必要があります。代わりに、ユニコードリテラルを使用して:あなたはUnicodeコードポイントの文字列(u'MyString')とバイト('MyString')の文字列を比較しようとしている

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

私はあなたは、Pythonを使っていると仮定しています3. us.encode('utf-8') == "MyString"戻りFalsestr.encode()関数はreturning a bytes objectあるため:

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

Python 3では、文字列はalready Unicodeなので、u'MyString'は余分です。

11

。これは「リンゴとオレンジ」の比較です。残念ながら、Pythonの2本の比較が有効であることをいくつかのケースでふり、代わりに常にFalseを返す:

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

それは正しい比較はどうあるべきかを決定するデザイナー/開発者として、あなた次第です。ここで1つの可能な方法である:すべてのu''スタイルの文字列がUTF-8でのバイトにエンコードすることができますので、私はおそらくいくつかの奇妙な場合を除いて、代わりにa == b.decode('UTF-8')の上記をお勧めします

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

、すべてではなく、バイト文字列が可能そのように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'は返しません。 –

+1

私は彼のタイプミスを彼に繰り返したように見えます。彼は編集後にPython 2を明示していますので、私も私の答えを編集します。 – wberry

関連する問題