正确处理土耳其大写和小写,需要修改/覆盖内置函数吗?

时间:2018-05-02 12:50:32

标签: python python-3.x built-in cyrillic turkish

我正在使用多语言文本数据,其中包括使用西里尔字母和土耳其语的俄语。我基本上必须比较两个文件my_filecheck_file中的单词,如果可以在my_file中找到check_file中的单词,请将它们写入保存元文件的输出文件中 - 从两个输入文件中获取有关这些单词的信息。

有些单词是小写的,而其他单词是大写的,所以我必须小写所有单词来比较它们。当我使用Python 3.6.5并且Python 3使用unicode作为默认值时,它会处理小写,然后为Cyrillic正确地大写单词。但是对于土耳其语,有些字母处理不正确。大写'İ'应对应小写'i',大写'I'应对应小写'ı',小写'i'应对应大写'İ',而不是如果我在控制台中键入以下内容的情况:

>>> print('İ'.lower())
i̇  # somewhat not rendered correctly, corresponds to unicode 'i\u0307'
>>> print('I'.lower())
i
>>> print('i'.upper())
I

我正在做如下(简化示例代码):

# python my_file check_file language

import sys

language = sys.argv[3]

# code to get the files as lists

my_file_list = [['ıspanak', 'N'], ['ısır', 'N'], ['acık', 'V']]
check_file_list = [['109', 'Ispanak', 'food_drink'], ['470', 'Isır', 'action_words'], [409, 'Acık', 'action_words']]

# get the lists as dict
my_dict = {}
check_dict = {}

for l in my_file_list:
    word = l[0].lower()
    pos = l[1]
    my_dict[word] = pos

for l in check_file_list:
    word_id = l[0]
    word = l[1].lower()
    word_cat = l[2]
    check_dict[word] = [word_id, word_cat]

# compare the two dicts
for word, pos in my_dict.items():
    if word in check_dict:
        word_id = check_dict[word][0]
        word_cat = check_dict[word][1]
        print(word, pos, word_id, word_cat)

这只给我一个结果,但它应该给我三个字:

acık V 409 action_words

到目前为止我基于this question做了什么:

  1. 阅读建议使用PyICU的已接受答案,但我希望我的代码可用,而无需人员安装,因此我没有实现它。
  2. 尝试在问题中提到的import localelocale.setlocale(locale.LC_ALL, 'tr_TR.UTF-8'),但它没有改变任何内容。
  3. 对于三个有问题的字母实现两个函数turkish_lower(self)turkish_upper(self),如第二个答案中所述,这似乎是唯一的解决方案:

    def turkish_lower(self):
        self = re.sub(r'İ', 'i', self)
        self = re.sub(r'I', 'ı', self)
        self = self.lower()
        return self
    
    def turkish_upper(self):
        self = re.sub(r'i', 'İ', self)
        self = self.upper()
        return self
    
  4. 但是如何在不必每次都检查if language == 'Turkish'的情况下使用这两个功能?我应该覆盖内置函数lower()upper()吗?如果是的话,pythonic的做法是什么?我应该为我正在使用的各种语言实现类,并覆盖土耳其语类中的内置函数吗?

2 个答案:

答案 0 :(得分:0)

我建议尝试为区域设置安装土耳其语语言包:

sudo apt-get install language-pack-tr
sudo dpkg-reconfigure locales  # *

您还可以使用终端命令$ locale -a

检查您在语言环境中使用的语言。

https://forum.yazbel.com/t/cozuldu-locale-setlocale-locale-lc-all-tr-tr-yapisinda-sorun-yasiyorum-turkce-karakter-sorunu/476

答案 1 :(得分:0)

您可以创建一个简单的“语言识别”字符串,该字符串将str子类化,并将进行适当的大写和小写,例如:

class LanguageAwareStr(str):
    lang = None


class RussianStr(LanguageAwareStr):
    lang = 'ru'


class TurkishStr(LanguageAwareStr):
    lang = 'tr'

    _case_lookup_upper = {'İ': 'i', 'I': 'ı'}  # lookup uppercase letters
    _case_lookup_lower = {v: k for (k, v) in _case_lookup_upper.items()}

    # here we override the lower() and upper() methods
    def lower(self):
        chars = [self._case_lookup_upper.get(c, c) for c in self]
        result = ''.join(chars).lower()
        cls = type(self)  # so we return a TurkishStr result
        return cls(result)

    def upper(self):
        chars = [self._case_lookup_lower.get(c, c) for c in self]
        result = ''.join(chars).upper()
        cls = type(self)  # so we return a TurkishStr result
        return cls(result)

然后,当您阅读字符串时,知道它是什么语言,可以将其包装在适当的LanguageAwareStr子类中,然后定期使用它:


from langaware import RussianStr, TurkishStr
if language == 'turkish':
    LangStr = TurkishStr  # can also create a dict to lookup the correct class

然后,当您阅读语言字符串时,只需将它们包装在对LangStr()的调用中:

for l in my_file_list:
    word = LangStr(l[0]).lower()
    pos = l[1]
    my_dict[word] = pos

for l in check_file_list:
    word_id = l[0]
    word = LangStr(l[1]).lower()
    word_cat = l[2]
    check_dict[word] = [word_id, word_cat]