全角转半角及其性能优化

新旧两版代码比较

旧版代码

PY2_FLAG = True
def full2half_1(str):
    """
    将字符串的全角符号转半角符号

    :param str: 待处理的字符串

    :return: 处理后的仅含半角符号字符串

    Examples
    --------
    >>> a = u"Hello word!"
    >>> print(full2half_1(a))
    Hello word!
    """
    def to_half(char):
        num = ord(char)   # 将utf-8编码转为16进制数
        if num == 0x3000: # 全角空格转半角空格
            num = 32
        elif 0xFF01 <= num <= 0xFF5E: # 这部分有93个,其余的不需要做转换了。
            num -= 0xfee0
        char = unichr(num) if PY2_FLAG else chr(num)  # in python 3, ord support as unichr,16进制数转为utf-8字符。
        return char

    if not str:
        return str

    n = [to_half(char) for char in str]
    return ''.join(n)

新版代码

def to_char(int):
    return unichr(int) if PY2_FLAG else chr(int)

full_half_mapping = {to_char(i): to_char(i - 0xfee0) for i in xrange(0xFF01, 0xFF5E)}
full_half_mapping[to_char(0x3000)] = to_char(32)


def full2half_2(text):
    return ''.join([full_half_mapping.get(t, t) for t in text])

测试效果

test_str = u"是磕副, ksl,。;‘;’【p1230979014795612040askdjkjklwekfioszndmmxcvk"
test_str = test_str * 50
print len(test_str)  
# out: 3000

%timeit full2half_1(test_str)
# out: 1000 loops, best of 3: 900 µs per loop

%timeit full2half_2(test_str)
# out: 1000 loops, best of 3: 434 µs per loop


test_str = u"是磕副, ksl,。;‘;’【p1230979014795612040askdjkjklwekfioszndmmxcvk"
test_str = test_str * 100
print len(test_str)  
# out: 6000

%timeit full2half_1(test_str)
# out: 1000 loops, best of 3: 1.77 ms per loop

%timeit full2half_2(test_str)
# out: 1000 loops, best of 3: 882 µs per loop

结论

新版方法比旧版方法要节约一半的时间

新版方法的时间消耗为 O(nO(dict.get)) O ( n O ( d i c t . g e t ) ) ,其中 O(dict.get) O ( d i c t . g e t ) 是Python中dict类型get操作的时间消耗,这里dict的长度为定值。 O(dict.get) O ( d i c t . g e t ) 小于 O(to_half) O ( t o _ h a l f ) 的时间消耗。

展望

进一步优化,还可以在 O(n) O ( n ) 上动手。现在程序需要扫描字符串一遍,但这并非必须的,因为UTF-8库中,中文情况下需要进行全角转半角的字符一共94个,我们检查及替换这些字符所花费的时间更短,要不要试一试。

你可能感兴趣的:(python)