Anda dapat mengganti sebagian besar kata-kata "rusak" ini dengan aslinya. Anda dapat dengan aman mengganti kata jika:
- suka
dene
atau rey
, itu bukan kata yang nyata
- seperti
define
atau firefly
, ada satu cara untuk sequeneces re-add ligatur ( ff
, fi
, fl
, ffi
, atau ffl
) dan membuat kata nyata
Sebagian besar masalah ligatur memenuhi kriteria ini. Namun, Anda tidak dapat mengganti:
us
karena itu adalah kata yang nyata, meskipun mungkin awalnya fluffs
- juga
affirm
, butterfly
, fielders
, fortifies
, flimflam
, misfits
...
cus
karena bisa menjadi salah satu cuffs
atauficus
- juga
stiffed
/ stifled
, rifle
/ riffle
, flung
/ fluffing
...
Dalam 496-ribu-kata kamus bahasa Inggris ini , ada 16.055 kata-kata yang mengandung setidaknya satu ff
, fi
, fl
, ffi
, atau ffl
, yang berubah menjadi 15.879 kata-kata ketika ligatures mereka dihapus. 173 kata-kata yang hilang bertabrakan seperti cuffs
dan ficus
, dan terakhir 3 adalah karena kamus yang berisi kata-kata ff
, fi
dan fl
.
790 dari kata-kata "ligatur-disingkirkan" ini adalah kata-kata nyata, seperti us
, tetapi 15089 adalah kata-kata rusak. 14960 dari kata-kata yang rusak dapat diganti dengan aman dengan kata aslinya, yang berarti 99,1% dari kata-kata yang rusak dapat diperbaiki dan 93,2% dari kata-kata asli yang berisi ligatur dapat dipulihkan setelah menyalin-menempelkan PDF. 6,8% dari kata-kata yang mengandung sekuens ligatur hilang dari tabrakan ( cus
) dan sub-kata ( us
), kecuali Anda memilih cara (konteks kata / dokumen?) Untuk memilih pengganti terbaik untuk setiap kata yang tidak memiliki jaminan penggantian.
Di bawah ini adalah skrip Python saya yang menghasilkan statistik di atas. Itu mengharapkan file teks kamus dengan satu kata per baris. Pada akhirnya ia menulis file CSV yang memetakan kata-kata rusak yang dapat diperbaiki menjadi kata-kata aslinya.
Berikut tautan untuk mengunduh CSV:
http://www.filedropper.com/brokenligaturewordfixes
Gabungkan pemetaan ini dengan sesuatu seperti skrip pengganti regex untuk mengganti sebagian besar kata-kata yang rusak.
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])