Bạn có thể thay thế hầu hết các từ "bị hỏng" này bằng bản gốc. Bạn có thể thay thế một từ một cách an toàn nếu:
- thích
dene
hay không rey
, nó không phải là một từ thực sự
- như
define
hoặc firefly
, có một cách để sequeneces tái add dấu gạch nối ( ff
, fi
, fl
, ffi
, hoặc ffl
) và làm cho một từ thực
Hầu hết các vấn đề về dây chằng phù hợp với các tiêu chí này. Tuy nhiên, bạn không thể thay thế:
us
bởi vì nó là một từ thực sự, mặc dù ban đầu nó có thể là fluffs
- cũng
affirm
, butterfly
, fielders
, fortifies
, flimflam
, misfits
...
cus
bởi vì nó có thể trở thành cuffs
hoặcficus
- cũng
stiffed
/ stifled
, rifle
/ riffle
, flung
/ fluffing
...
Trong 496 ngàn từ trong từ điển tiếng Anh này , có 16.055 từ mà chứa ít nhất một ff
, fi
, fl
, ffi
, hay ffl
, mà biến thành 15.879 từ khi ligature họ bị xóa. 173 của những lời thiếu va chạm như cuffs
và ficus
, và cuối cùng 3 là vì từ điển có chứa các từ ff
, fi
và fl
.
790 trong số những từ "loại bỏ dây chằng" này là những từ thực sự, giống như us
, nhưng 15089 là những từ bị hỏng. 14960 từ bị hỏng có thể được thay thế một cách an toàn bằng từ gốc, có nghĩa là 99,1% từ bị hỏng có thể sửa được và 93,2% từ gốc có chứa một chữ ghép có thể được phục hồi sau khi sao chép PDF. 6,8% từ có chứa chuỗi chữ ghép bị mất cho các va chạm ( cus
) và từ phụ ( us
), trừ khi bạn chọn một cách nào đó (ngữ cảnh từ / tài liệu?) Để chọn từ thay thế tốt nhất cho mỗi từ không được bảo đảm thay thế.
Dưới đây là tập lệnh Python của tôi đã tạo ra số liệu thống kê ở trên. Nó mong đợi một tệp văn bản từ điển với một từ trên mỗi dòng. Cuối cùng, nó viết một tệp CSV ánh xạ các từ bị hỏng có thể sửa thành các từ gốc của chúng.
Đây là một liên kết để tải xuống CSV:
http://www.filedropper.com/brokenligaturewordfixes
Kết hợp ánh xạ này với một cái gì đó giống như một tập lệnh thay thế regex để thay thế hầu hết các từ bị hỏng.
import csv
import itertools
import operator
import re
dictionary_file_path = 'dictionary.txt'
broken_word_fixes_file_path = 'broken_word_fixes.csv'
ligatures = 'ffi', 'ffl', 'ff', 'fi', 'fl'
with open(dictionary_file_path, 'r') as dictionary_file:
dictionary_words = list(set(line.strip()
for line in dictionary_file.readlines()))
broken_word_fixes = {}
ligature_words = set()
ligature_removed_words = set()
broken_words = set()
multi_ligature_words = set()
# Find broken word fixes for words with one ligature sequence
# Example: "dene" --> "define"
words_and_ligatures = list(itertools.product(dictionary_words, ligatures))
for i, (word, ligature) in enumerate(words_and_ligatures):
if i % 50000 == 0:
print('1-ligature words {percent:.3g}% complete'
.format(percent=100 * i / len(words_and_ligatures)))
for ligature_match in re.finditer(ligature, word):
if word in ligature_words:
multi_ligature_words.add(word)
ligature_words.add(word)
if word == ligature:
break
# Skip words that contain a larger ligature
if (('ffi' in word and ligature != 'ffi') or
('ffl' in word and ligature != 'ffl')):
break
# Replace ligatures with dots to avoid creating new ligatures
# Example: "offline" --> "of.ine" to avoid creating "fi"
ligature_removed_word = (word[:ligature_match.start()] +
'.' +
word[ligature_match.end():])
# Skip words that contain another ligature
if any(ligature in ligature_removed_word for ligature in ligatures):
continue
ligature_removed_word = ligature_removed_word.replace('.', '')
ligature_removed_words.add(ligature_removed_word)
if ligature_removed_word not in dictionary_words:
broken_word = ligature_removed_word
broken_words.add(broken_word)
if broken_word not in broken_word_fixes:
broken_word_fixes[broken_word] = word
else:
# Ignore broken words with multiple possible fixes
# Example: "cus" --> "cuffs" or "ficus"
broken_word_fixes[broken_word] = None
# Find broken word fixes for word with multiple ligature sequences
# Example: "rey" --> "firefly"
multi_ligature_words = sorted(multi_ligature_words)
numbers_of_ligatures_in_word = 2, 3
for number_of_ligatures_in_word in numbers_of_ligatures_in_word:
ligature_lists = itertools.combinations_with_replacement(
ligatures, r=number_of_ligatures_in_word
)
words_and_ligature_lists = list(itertools.product(
multi_ligature_words, ligature_lists
))
for i, (word, ligature_list) in enumerate(words_and_ligature_lists):
if i % 1000 == 0:
print('{n}-ligature words {percent:.3g}% complete'
.format(n=number_of_ligatures_in_word,
percent=100 * i / len(words_and_ligature_lists)))
# Skip words that contain a larger ligature
if (('ffi' in word and 'ffi' not in ligature_list) or
('ffl' in word and 'ffl' not in ligature_list)):
continue
ligature_removed_word = word
for ligature in ligature_list:
ligature_matches = list(re.finditer(ligature, ligature_removed_word))
if not ligature_matches:
break
ligature_match = ligature_matches[0]
# Replace ligatures with dots to avoid creating new ligatures
# Example: "offline" --> "of.ine" to avoid creating "fi"
ligature_removed_word = (
ligature_removed_word[:ligature_match.start()] +
'.' +
ligature_removed_word[ligature_match.end():]
)
else:
# Skip words that contain another ligature
if any(ligature in ligature_removed_word for ligature in ligatures):
continue
ligature_removed_word = ligature_removed_word.replace('.', '')
ligature_removed_words.add(ligature_removed_word)
if ligature_removed_word not in dictionary_words:
broken_word = ligature_removed_word
broken_words.add(broken_word)
if broken_word not in broken_word_fixes:
broken_word_fixes[broken_word] = word
else:
# Ignore broken words with multiple possible fixes
# Example: "ung" --> "flung" or "fluffing"
broken_word_fixes[broken_word] = None
# Remove broken words with multiple possible fixes
for broken_word, fixed_word in broken_word_fixes.copy().items():
if not fixed_word:
broken_word_fixes.pop(broken_word)
number_of_ligature_words = len(ligature_words)
number_of_ligature_removed_words = len(ligature_removed_words)
number_of_broken_words = len(broken_words)
number_of_fixable_broken_words = len(
[word for word in set(broken_word_fixes.keys())
if word and broken_word_fixes[word]]
)
number_of_recoverable_ligature_words = len(
[word for word in set(broken_word_fixes.values())
if word]
)
print(number_of_ligature_words, 'ligature words')
print(number_of_ligature_removed_words, 'ligature-removed words')
print(number_of_broken_words, 'broken words')
print(number_of_fixable_broken_words,
'fixable broken words ({percent:.3g}% fixable)'
.format(percent=(
100 * number_of_fixable_broken_words / number_of_broken_words
)))
print(number_of_recoverable_ligature_words,
'recoverable ligature words ({percent:.3g}% recoverable)'
'(for at least one broken word)'
.format(percent=(
100 * number_of_recoverable_ligature_words / number_of_ligature_words
)))
with open(broken_word_fixes_file_path, 'w+', newline='') as broken_word_fixes_file:
csv_writer = csv.writer(broken_word_fixes_file)
sorted_broken_word_fixes = sorted(broken_word_fixes.items(),
key=operator.itemgetter(0))
for broken_word, fixed_word in sorted_broken_word_fixes:
csv_writer.writerow([broken_word, fixed_word])