-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathtypos.py
More file actions
72 lines (47 loc) · 1.97 KB
/
Copy pathtypos.py
File metadata and controls
72 lines (47 loc) · 1.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import string
from collections import deque
def insertions(a, b, lowercase=True):
return string.ascii_lowercase if lowercase else string.ascii_uppercase
def substitutions(x, lowercase=True):
return string.ascii_lowercase if lowercase else string.ascii_uppercase
def concat(*tokens):
return "".join(tokens)
def generate_insertions(s, lowercase=True):
for i in range(len(s)):
xs = insertions(s[i-1:i], s[i:i+1], lowercase=lowercase)
yield from (concat(s[:i], x, s[i:]) for x in xs)
def generate_substitutions(s, lowercase=True):
for i in range(len(s)):
xs = substitutions(s[i], lowercase=lowercase)
yield from (concat(s[:i], x, s[i+1:]) for x in xs)
def generate_transpositions(s):
return (concat(s[:i], s[i+1], s[i], s[i+2:]) for i in range(len(s) - 1))
def generate_deletions(s):
for i in range(len(s)):
yield concat(s[:i], s[i+1:])
class Typos(object):
def __init__(self, root, max_edit_distance=None, visited=None, lowercase=True):
self.root = root
self.visited = visited or set()
self.frontier = deque([(0, root)])
self.max_edit_distance = max_edit_distance
self.lowercase = lowercase
def __iter__(self):
if self.visited and not self.frontier:
return iter(self.visited)
def neighbors(s):
yield from generate_deletions(s)
yield from generate_insertions(s, lowercase=self.lowercase)
yield from generate_substitutions(s, lowercase=self.lowercase)
yield from generate_transpositions(s)
def prune(d, s):
if self.max_edit_distance and d > self.max_edit_distance:
return True
if s in self.visited:
return True
return False
while self.frontier:
d, s = self.frontier.popleft()
self.visited.add(s)
yield s
self.frontier.extend((d+1, n) for n in neighbors(s) if not prune(d+1,n))