代码之家  ›  专栏  ›  技术社区  ›  d33tah

如何标记拼音,最好使用嵌套、重叠的正则表达式组?

  •  0
  • d33tah  · 技术社区  · 6 年前

    我正在尝试标记一个汉语拼音符号(没有音调)。考虑以下代码:

    finals = ['a',
            'o',
            'e',
            'ai',
            'ei',
            'ao',
            'ou',                                                                                                                                                                       
            'an',                                                                                                                                                                       
            'ang',
            'en',
            'eng',
            'er',
            'u',
            'ua',
            'uo',
            'uai',
            'ui',
            'uan',
            'uang',
            'un',
            'ueng',
            'ong',
            'i',
            'i',
            'ia',
            'ie',
            'iao',
            'iu',
            'ian',
            'iang',
            'in',
            'ing',
            'ü',
            'üe',
            'üan',
            'ün',
            'iong']
    initials = ['p',
              'm',
              'f',
              'd',
              't',
              'n',
              'l',
              'g',
              'k',
              'h',
              'j',
              'q',
              'x',
              'z',
              'h',
              'c',
              'h',
              's',
              'h',
              'r',
              'z',
              'c',
              's']
    others = ['a',
            'o',
            'e',
            'ai',
            'ei',
            'ao',
            'ou',
            'an',
            'ang',
            'en',
            'eng',
            'er',
            'wu',
            'wa',
            'wo',
            'wai',
            'wei',
            'wan',
            'wang',
            'wen',
            'weng',
            'yi',
            'ya',
            'ye',
            'yao',
            'you',
            'yan',
            'yang',
            'yin',
            'ying',
            'yu',
            'yue',
            'yuan',
            'yun',
            'yong']
    
    r = '^((%s)(%s)|%s)+$' % ('|'.join(initials), '|'.join(finals), '|'.join(others))
    import re
    m = re.match(r, 'yinwei')
    print(m.groups())
    

    我希望能 ['yin','wei'] (两个连续的外部组),但出于某种原因,只得到了“微”。为什么这个代码不起作用,以及如何修复它?我也尝试了以下方法,但它随机给出 ['yin', 'wei'] ['yi', 'wei] :

    import regex
    r = '|'.join({i + f for i in initials for f in finals}.union(set(others)))
    print(regex.findall(r, 'yinwei'))
    

    编辑:我正要接受这是一个副本 4963691 因为ekhumuro的答案,但它不适用于 bangongshi 作为输入-而不是 ['ban','gong','shi'] 我们要走了 ['bang', 'o', 'shi'] .正因为如此,我希望这个问题与其他问题分开考虑 this one .

    1 回复  |  直到 6 年前
        1
  •  1
  •   ekhumoro    6 年前

    这个 re 模块与运算符(例如)一起使用时不会累积组 + .在您的示例中,它将首先匹配 'yin' ,然后匹配 'wei' -但它只会保留最后一组匹配的组(所以 m.groups() 只会回来 ['wei', None, None] )。但是,您的regexp仍将正确获取 整场比赛 -所以 m.group() 会回来的 'yinwei' .

    列表中的元素似乎不会产生任何重叠的组合。也就是说:没有 initials[n] + finals[n] 这是重复的 others .然而,也有重叠的元素 在内部 每个列表(例如。 yi|yin|ying 在里面 其他的 ),但这可以通过按长度降序排列列表来克服。

    这意味着你可以很容易地将一个拼音词分解成如下元素:

    import re
    
    initials.sort(key=len, reverse=True)
    finals.sort(key=len, reverse=True)
    others.sort(key=len, reverse=True)
    
    r = '(?:%s)(?:%s)|(?:%s)' % ('|'.join(initials), '|'.join(finals), '|'.join(others))
    print(re.findall(r, 'yinwei'))
    

    输出:

    ['yin', 'wei']
    

    使现代化 :

    在看了一本书之后 reliable source ,看来你解析拼音的方法太简单了。这个 table of combinations 这表明并非所有的可能性都是有效的。它还表明,一些组合是模糊的(从纯粹的句法角度来看)。例如 可以解析为 [l + iang] [l + i], [ang] 此外,并不是所有的延续都是有效的,因此需要一些后视断言。这表明,需要一种更复杂的方法,而不是简单地从左到右顺序匹配。经过一番搜索,我发现前面的一个问题似乎涵盖了同样的问题:

    然而,用一个regexp来解决这个问题似乎并不简单,因此您可能需要考虑寻找一个第三方库,它知道如何处理所有棘手的边缘情况。