CheckiO 是面向初学者和高级程序员的编码游戏,使用 Python 和 JavaScript 解决棘手的挑战和有趣的任务,从而提高你的编码技能,本博客主要记录自己用 Python 在闯关时的做题思路和实现代码,同时也学习学习其他大神写的代码。
CheckiO 官网:https://checkio.org/
我的 CheckiO 主页:https://py.checkio.org/user/TRHX/
CheckiO 题解系列专栏:https://itrhx.blog.csdn.net/category_9536424.html
CheckiO 所有题解源代码:https://github.com/TRHX/Python-CheckiO-Exercise
题目描述
【Remove Accents】:给定一个 Unicode 字符串,去除其中的重音符号,é
:带重音的字母,e
:不带重音的字母,̀
:独立的重音符号。
【链接】:https://py.checkio.org/mission/remove-accents/
【输入】:字符串(Unicode)
【输出】:无重音的 Unicode 字符串
【前提】:0≤|input|≤40
【范例】:
checkio(u"préfèrent") == u"preferent"
checkio(u"loài trăn lớn") == u"loai tran lon"
解题思路
了解这些特殊字符,比如:Spicy Jalapeño
使用的是拉丁字母“n”紧跟着一个“~”组合而成的字符(U+0303),也就是 Spicy Jalapen\u0303o
利用 unicodedata
模块,normalize()
方法将字符串进行分解,利用 combining()
方法对字符做检查,判断它是否为一个组合型字符(包含重音字符等特殊字符),如果不是组合型字符,则将其组成一个新的字符串。
知识扩展
unicodedata.normalize(form, unistr)
方法:
把一串 Unicode 字符串转换为普通格式的字符串,具体格式(form)支持 NFC、NFKC、NFD 和 NFKD 格式。
一些文本元素既可以使用静态的预先组合好的形式,也可使用动态组合的形式。Unicode 字符的不同表示序列被认为是等价的。如果两个或多个序列被认为是等价的,Unicode 标准不规定哪一种特定的序列是正确的,而认为每一个序列只不过与其它序列等价。如果需要一种单一的表示方式,可以使用一种规范化的 Unicode 文本形式来减少不想要区别。Unicode 标准定义了四种规范化形式: Normalization Form D (NFD),Normalization Form KD (NFKD),Normalization Form C (NFC),和Normalization Form KC (NFKC)。
NFD 和 NFKD 将可能的字符进行分解,而 NFC 和 NFKC 将可能的字符进行组合。
unicodedata 模块文档:https://docs.python.org/zh-cn/3.7/library/unicodedata.html
以下举例说明不同格式(form)的区别:
例(NFC):
import unicodedatain_string = u"préfèrent"
for c in unicodedata.normalize('NFC', in_string):print(c)
输出结果
p
r
é
f
è
r
e
n
t
例(NFD):
import unicodedatain_string = u"préfèrent"
for c in unicodedata.normalize('NFD', in_string):print(c)
输出结果:
p
r
e
́
f
e
̀
r
e
n
t
代码实现
import unicodedatadef checkio(in_string):# remove accentsreturn ''.join(i for i in unicodedata.normalize('NFD', in_string) if not unicodedata.combining(i))# These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':assert checkio(u"préfèrent") == u"preferent"assert checkio(u"loài trăn lớn") == u"loai tran lon"print('Done')
大神解答
大神解答 NO.1
from unicodedata import category, normalizedef checkio(string):return ''.join(c for c in normalize('NFKD', string) if category(c) != 'Mn')
大神解答 NO.2
from unicodedata import normalize, combining as accent
from functools import partial as curry
from itertools import filterfalse as removeiftake_apart = curry(normalize, "NFD")
remove_accents = curry(removeif, accent)
make_str = ''.joindef compose(*funcs):def composition(x):for func in funcs:x = func(x)return xreturn compositioncheckio = compose(take_apart, remove_accents, make_str)
大神解答 NO.3
from unicodedata import category as cat, name
import redef checkio(s):return ''.join(eval("'{}'.{}er()".format( # evaluator*re.findall('LETTER (.?)', name(c)) or c, # "letters"'upp' if cat(c) == 'Lu' else 'low')) # letter casefor c in filter(lambda c: cat(c)[0] in 'PuZzLeS', s)) # letter generator
大神解答 NO.4
from unicodedata import normalizedef checkio(s):return ''.join(c for c in normalize('NFD', s) if c not in u"̨̧̛̣̱̮̉̇̊̄̃̑̂̏̋̈̌̆̀́")