Python: как сравнить юникод с текстом ascii? - PullRequest
0 голосов
/ 06 октября 2011

Я пытаюсь преобразовать символы из одного списка в символы из другого списка с тем же индексом на японском языке (zenkaku to hangaku moji, для тех, кто заинтересован), и я не могу заставить сравнение работать. Я декодирую в utf-8 перед сравнением (декодирование в ascii сломало программу), но сравнение никогда не возвращает истину. Кто-нибудь знает, что я делаю не так? Вот код (отступы немного дурацкие из-за редактора SO):

#!C:\Python27\python.exe
# coding=utf-8
import os
import shutil
import sys

zk = [
'。',
'、',
'「',
'」',
'(',
')',
'!',
'?',
'・',
'/',
'ア','イ','ウ','エ','オ',
'カ','キ','ク','ケ','コ',
'サ','シ','ス','セ','ソ',
'ザ','ジ','ズ','ゼ','ゾ',
'タ','チ','ツ','テ','ト',
'ダ','ヂ','ヅ','デ','ド',
'ラ','リ','ル','レ','ロ',
'マ','ミ','ム','メ','モ',
'ナ','ニ','ヌ','ネ','ノ',
'ハ','ヒ','フ','ヘ','ホ',
'バ','ビ','ブ','ベ','ボ',
'パ','ピ','プ','ペ','ポ',
'ヤ','ユ','ヨ','ヲ','ン','ッ'
]

hk = [
'。',
'、',
'「',
'」',
'(',
')',
'!',
'?',
'・',
'/',
'ア','イ','ウ','エ','オ',
'カ','キ','ク','ケ','コ',
'サ','シ','ス','セ','ソ',
'ザ','ジ','ズ','ゼ','ゾ',
'タ','チ','ツ','テ','ト',
'ダ','ヂ','ヅ','デ','ド',
'ラ','リ','ル','レ','ロ',
'マ','ミ','ム','メ','モ',
'ナ','ニ','ヌ','ネ','ノ',
'ハ','ヒ','フ','ヘ','ホ',
'バ','ビ','ブ','ベ','ボ',
'パ','ピ','プ','ペ','ポ',
'ヤ','ユ','ヨ','ヲ','ン','ッ'
]

def main():
if len(sys.argv) > 1:
    filename = sys.argv[1]
else:
    print("Please specify a file to check.")
    return

try:
    f = open(filename, 'r')
except IOError as e:
    print("Sorry! The file doesn't exist.")
    return

filecontent = f.read()
f.close()

#y = zk[29]
#print y.decode('utf-8')

for f in filecontent:
    for z in zk:
        if f == z.decode('utf-8'):
        print f

print filename



if __name__ == "__main__":
main()

Я пропустил шаг?

Ответы [ 3 ]

3 голосов
/ 06 октября 2011

Несколько.

zk = [
u'。',
u'、',
u'「',
 ...

 ...
    f = codecs.open(filename, 'r', encoding='utf-8')
 ...

Я позволю вам потренироваться с остальными сейчас, когда тяжелая работа выполнена.

1 голос
/ 06 октября 2011

Убедитесь, что списки zk и hk содержат строки Unicode. Либо используйте литералы Unicode, например, u'a', либо декодируйте их во время выполнения:

fromutf8 = lambda s: s.decode('utf-8') if not isinstance(s, unicode) else s
zk = map(fromutf8, zk)
hk = map(fromutf8, hk)

Вы можете использовать unicode.translate() для преобразования символов в одном списке в символы в другом списке с тем же индексом:

import codecs

translation_table = dict(zip(map(ord,zk), hk))
with codecs.open(sys.argv[1], encoding='utf-8') as f:
     for line in f:
         print line.translate(translation_table),
0 голосов
/ 30 апреля 2012

Вам нужно преобразовать все в одну и ту же форму, а форма - это строки Unicode. Строки Unicode не имеют кодировки в смысле .encode() или .decode(). Если строка не в Юникоде, это фактически поток байтов, который выражает значение в некоторой кодировке. При конвертации в Unicode вам нужно .decode(). При сохранении строки Unicode в последовательность байтов необходимо .encode() абстракция к конкретным байтам.

Таким образом, при загрузке строк Unicode из файла в кодировке UTF-8, или вам нужно прочитать его в старые строки (не Unicode, последовательности байтов) и затем .decode('utf-8'), или вы можете использовать `codecs.open (..., encoding = 'utf-8') - тогда вы получите строки Unicode автоматически.

Форма # coding=utf-8 не является обычной, но все в порядке ... если редактор (я имею в виду инструмент, который вы используете для написания текста) также думает так. Тогда старые строки корректно отображаются редактором. В случае, если они должны быть .decode('utf-8') d, чтобы получить Unicode. Старые строки с символами ASCII только в одном источнике также можно преобразовать в Unicode с помощью .decode('utf-8').

Подводя итог: вы de кодируете от байтов до Unicode, и вы en кодируете строки Unicode в последовательность байтов. Из вопроса видно, что вы делаете наоборот.

Совершенно неверно следующее:

for f in filecontent:
    for z in zk:
        if f == z.decode('utf-8'):
            print f

, потому что filecontent является результатом f.read(). Таким образом, это последовательность байтов. f в цикле составляет один байт. Код z.decode ('utf-8') возвращает один символ Unicode. Их нельзя сравнивать. (Кстати, f является своего рода вводящим в заблуждение именем для байтового значения.)

...