如何结合平假名和片假名之间转换的两个相似功能?

时间:2017-11-14 05:48:28

标签: python unicode char ord

我有两个功能可以转换片假名和平假名,它们看起来一样:

katakana_minus_hiragana = 0x30a1 - 0x3041 # KATAKANA LETTER A - HIRAGANA A

def is_hirgana(char):
    return 0x3040 < ord(char[0]) and ord(char[0]) < 0x3097

def is_katakana(char):
    return 0x30a0 < ord(char[0]) and ord(char[0]) < 0x30f7

def hiragana_to_katakana(hiragana_text):
    katakana_text = ""
    max_len = 0
    for i, char in enumerate(hiragana_text):
        if is_hirgana(char):
            katakana_text += chr(ord(char) + katakana_minus_hiragana)
            max_len += 1
        else:
            break
    return katakana_text, max_len

def katakana_to_hiragana(katakana_text):
    hiragana_text = ""
    max_len = 0
    for i, char in enumerate(katakana_text):
        if is_katakana(char):
            hiragana_text += chr(ord(char) - katakana_minus_hiragana)
            max_len += 1
        else:
            break
    return hiragana_text, max_len

有没有办法将hiragana_to_katakana()katakana_to_hiragana()简化为鸭型函数或超级/元函数?

E.g。

之类的东西
def convert_hk_kh(text, charset_range, offset):
    charset_start, charset_end = charset_range
    output_text = ""
    max_len = 0
    for i, char in enumerate(text):
        if charset_start < ord(char[0]) and ord(char[0]) < charset_end:
            output_text += chr(ord(char) + offset)
            max_len +=1 
        else:
            break
    return output_text, max_len


def katakana_to_hiragana(katakana_text):
    return convert_hk_kh(katakana_text, (0x30a0, 0x30f7), -katakana_minus_hiragana)


def hiragana_to_katakana(hiragana_text):
    return convert_hk_kh(hiragana_text, (0x3040, 0x3097), katakana_minus_hiragana)

是否有其他pythonic方法来简化非常相似的两个函数?

EDITED

还有https://github.com/olsgaard/Japanese_nlp_scripts似乎与str.translate做同样的事情。这更有效吗?更pythonic?

2 个答案:

答案 0 :(得分:1)

我做这样的事情:

KATAKANA_HIRGANA_SHIFT = 0x30a1 - 0x3041  # KATAKANA LETTER A - HIRAGANA A

def shift_chars_prefix(text, amount, condition):
    output = ''

    for last_index, char in enumerate(text):
        if not condition(char):
            break

        output += chr(ord(char) + amount)

    return output, last_index

def katakana_to_hiragana(text):
    return shift_chars_prefix(text, -KATAKANA_HIRGANA_SHIFT, lambda c: '\u30a0' < c < '\u30f7')

def hiragana_to_katakana(text):
    return shift_chars_prefix(text, KATAKANA_HIRGANA_SHIFT, lambda c: '\u3040' < c < '\u3097')

如果您没有返回替换前缀的长度,也可以使用正则表达式:

import re

KATAKANA_HIRGANA_SHIFT = 0x30a1 - 0x3041  # KATAKANA LETTER A - HIRAGANA A

def shift_by(n):
    def replacer(match):
        return ''.join(chr(ord(c) + n) for c in match.group(0))

    return replacer

def katakana_to_hiragana(text):
    return re.sub(r'^[\u30a1-\u30f6]+', shift_by(KATAKANA_HIRGANA_SHIFT), text)

def hiragana_to_katakana(text):
    return re.sub(r'^[\u3041-\u3096]+', shift_by(-KATAKANA_HIRGANA_SHIFT), text)

答案 1 :(得分:1)

这是一种将各种假名转换为另一种假名的功能。 与给定的功能不同,它在遇到时不会停止 非假名,但只是通过这些角色而不改变 它们。

请注意,假名类型之间的转换并不像这样简单;对于 例如,在平假名中,ええ或えい指示长“e”音 (例如,おねえ姐姐,せんせい老师),而在片假名1 使用chōonpu(オネー,せんせー)。外面有假名字符 您使用的范围也是如此。

def switch_kana_type(kana_text):
    """Replace each kind of kana with the other kind. Other characters are
    passed through unchanged."""

    output_text = ''
    for c in kana_text:
        if is_hiragana(c):   # Note typo fix of "is_hirgana"
            output_text += chr(ord(c) + katakana_minus_hiragana)
        elif is_katakana(char):
            output_text += chr(ord(c) - katakana_minus_hiragana)
        else:
            output_text += c;
    return output_text, len(output_text)