简介:
这个代码是看了Peter大神的文章自己模仿这写的,基本就是copy人家的思路,不过自己在代码之间添加了一些注释。
自己写这个的目的是练习自己写Python代码的能力,而且在这个过程中确实收获还是蛮多的!
代码及其注释
# -*- coding: utf-8 -*-
import re
from collections import Counter
def words(text):
return re.findall(r'\w+', text.lower())
# findall函数作用(可查看用户手册)在这里就是用来将txt中的每一个单词进行分离,在返回一个字符串列表
WORDS = Counter(words(open('D:\\PythonWorkSpace\\big.txt').read()))
# 这里的WORDS就是一个无序的集合,里面存储的是K-V:K是单词,V是单词在txt中出现的次数。这个是由Count函数使得的
def P(word, N = sum(WORDS.values())):
return WORDS[word] / N
# P这个函数是用来计算word这个词在txt样本中出现的概率,当word没有出现过,WORDS[word]会返回0
def known(words):
# known这个函数返回一个集合,集合的内容是即在words这个集合中,又在WORDS中的单词
return set(w for w in words if w in WORDS)
def edits1(word):
# edits1函数的作用是返回对word这个单词一次编辑后可能得到的所有结果的集合
letters = 'abcdefghijklmnopqrstuvwxyz'
splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]
# splits 在这里就是由tuple组成的list,每一个tuple是word单词的分解形式
# 这里面字符串索引得认真去研究一波,比如word[0:0]结果是空字符,word[aN:aN]结果也是很空字符
deletes = [L + R[1:] for L, R in splits if R]
# 这里面的R如果是空字符,就判断为False
# deletes 在这里的作用就是得到word删掉一个字母的所有字符的集合
transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R) > 1]
# transposes 在这里的作用就是将word单词中任意两个字母调换一次位置后得到的所有单词的集合
replaces = [L + c + R[1:] for L, R in splits if R for c in letters]
# replaces 在这里的用途是将word单词中删掉一个字母后可能得到的单词的集合
inserts = [L + c + R for L, R in splits for c in letters]
# inserts 在此处的作用是插入一个字母到word单词中后可能得到的单词的集合
return set(deletes + transposes + replaces + inserts)
def edits2(word):
# edits2函数的作用是返回对word这个单词进行两次编辑后可能得到的所有结果的集合
return (e2 for e1 in edits1(word) for e2 in edits1(e1))
def candidates(word):
# candidates函数返回的内容:如果word在txt中出现过,则就返回word,如果没有的话,就返回对word编辑一次后获得的字符集中在txt中出现过的字符构成的集合,如果还是没有的话就返回二次编辑的,如果二次编辑的也没有的话,就返回word
# 看了写这个代码的人的解释,这个函数算是一个错误模型,用来保证所获得的结果是比较可信的
return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])
def correction(word):
return max(candidates(word), key = P)
下面一个代码是测试用的:
import sys
sys.path.append('D:\\PythonWorkSpace\\SpellingCheck.py')
import time
import SpellingCheck
def spelltest(tests, verbose = True):
start = time.clock()
good, unknown = 0, 0
n = len(tests)
for right, wrong in tests:
w = SpellingCheck.correction(wrong)
good += (w == right)
if w != right:
unknown += (right not in SpellingCheck.WORDS)
if verbose:
print('correction( {} ) => {} ( {} ); except {} ( {} )'.format(wrong, w, SpellingCheck.WORDS[w], right, SpellingCheck.WORDS[right]))
dt = time.clock() - start
print('{:.0%} of {} correct ({:.0%} unknown) at {:.0f} words per second'.format(good / n, n, unknown / n, n / dt))
def Testset(lines):
return [(right, wrong) for (right, wrongs) in (line.split(':') for line in lines) for wrong in wrongs.split()]
spelltest(Testset(open('D:\\PythonWorkSpace\\spell-testset.txt')))
说明
我将代码中测试的big.txt和spell-testset.txt放在D:\\PythonWorkSpace
目录面
- big.txt文件下载地址:
http://norvig.com/big.txt
- spell-testset.txt文件下载地址:
http://norvig.com/spell-testset1.txt
总结
只能说自己的Python基础还是比较薄弱的,得加强!