Ofis Benzeri Yazım Kontrol Uygulaması

C# ile basit bir Türkçe yazım kontrolü aracı oluşturacağız. Aracımız Microsoft Office Programlarında olduğu gibi kelimemizi kontrol edip eğer kelimemiz hatalıysa altını çizecek. Kelime yazım kontrolünde kullanacağımız kontrol sınıfı Phyton ile  kodlanmış Spell Corrector aracının C# a dönüştürülmüş hali. http://norvig.com/spell-correct.html adresinden ulaşabileceğiniz bu basit uygulama Phyton ile sadece 21 satır kod ile tamamlanmış. (Boşlukları saymadan)

spellCorrect

Kodun Tamamını şu şekilde.

import re, collections

def words(text): return re.findall('[a-z]+', text.lower()) 

def train(features):
    model = collections.defaultdict(lambda: 1)
    for f in features:
        model[f] += 1
    return model

NWORDS = train(words(file('big.txt').read()))

alphabet = 'abcdefghijklmnopqrstuvwxyz'

def edits1(word):
   splits     = [(word[:i], word[i:]) for i in range(len(word) + 1)]
   deletes    = [a + b[1:] for a, b in splits if b]
   transposes = [a + b[1] + b[0] + b[2:] for a, b in splits if len(b)>1]
   replaces   = [a + c + b[1:] for a, b in splits for c in alphabet if b]
   inserts    = [a + c + b     for a, b in splits for c in alphabet]
   return set(deletes + transposes + replaces + inserts)

def known_edits2(word):
    return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)

def known(words): return set(w for w in words if w in NWORDS)

def correct(word):
    candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
    return max(candidates, key=NWORDS.get)

Phyton kodunu şu şekilde kullanıyoruz.

>>> correct('speling')
'spelling'
>>> correct('korrecter')
'corrector'

Kodun açıklamasını yukarıda verdiğim linkte okuyabilirsiniz. (İngilizce) Ve yine bu kodun diğer programlama dillerinde yazılmış halleride yine aynı sayfada bulunuyor.

Language Lines
Code
Author
(and link to implementation)
Awk 15 Tiago “PacMan” Peczenyj
Awk 28 Gregory Grefenstette
C 184 Marcelo Toledo
C++ 98 Felipe Farinon
C# 43 Lorenzo Stoakes
C# 69 Frederic Torres
Clojure 18 Rich Hickey
D 23 Leonardo M
Erlang 87 Federico Feroldi
F# 16 Dejan Jelovic
F# 34 Sebastian G
Go 57 Yi Wang
Groovy 22 Rael Cunha
Haskell 24 Grzegorz
Java 35 Rael Cunha
Java 372 Dominik Schulz
Javascript 92 Shine Xavier
Javascript 53 Panagiotis Astithas
Lisp 26 Mikael Jansson
Perl 63 riffraff
PHP 68 Felipe Ribeiro
PHP 103 Joe Sanders
Python 21 Peter Norvig
Rebol 133 Cyphre
Ruby 34 Brian Adkins
Scala 23 Thomas Jung
Scheme 45 Shiro
Scheme 89 Jens Axel

Ben C# için bu kodun uyarlamasını kullanacağım. http://frederictorres.blogspot.com/2011/04/how-to-write-spelling-corrector-from.html adresindeki kodu kullancağız uygulamamızı türkçeleştirmekle başlayalım. Bu kodun çalışması için projemize DinamicSugar kütüphanelerini dahil etmeliyiz.

Nuget manager ile DynamicSugar Kütüphanesini Kurmak için
(1) Menu Tools -> Library Package Manager -> Library Package Console
(2) Install-package DynamicSugar
(3) Paste the code in the file program.cs above the program class
(4) Aşağıdaki 2 using satırını ekleyin.
using System.Threading.Tasks;
using DynamicSugar;

class SpellCorrector
{

Dictionary<string, int> DWORDS;
const string ALPHABET = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";//Türkçe Karakterleri ekliyoruz

public SpellCorrector()
{

DWORDS = this.Train(this.Words(System.IO.File.ReadAllText("tr.txt")));//tr.txt dosyası bizim türkçe kelimelerin yer aldığı listemiz.
}
List<string> Words(string text)
{

return Regex.Matches(text.ToLower(), "[a-zığüşöç]+").ToList(); //Türkçe Karakterleri ekliyoruz
}
Dictionary<string, int> Train(List<string> features)
{

var model = new Dictionary<string, int>();
foreach (var f in features)
model[f] = model.Get(f, 0) + 1;
return model;
}
class StringPair
{

public string a, b;
}
List<string> Edits1(string word)
{

var splits = DS.Range(word.Length + 1).Map(i => new StringPair { a = word.Slice(0, i), b = word.Slice(i) });
var deletes = splits.Map(s => s.a + s.b.Slice(1));
var transposes = splits.Map(s => s.b.Length > 1 ? s.a + s.b[1] + s.b[0] + s.b.Slice(2) : "**");

var replaces = new List<string>();
foreach (var s in splits)
foreach (var c in ALPHABET)
if (s.b.Length > 0)
replaces.Add(s.a + c + s.b.Slice(1, -1));

var inserts = new List<string>();
foreach (var s in splits)
foreach (var c in ALPHABET)
inserts.Add(s.a + c + s.b);

return deletes.Add(transposes).Add(replaces).Add(inserts);
}
List<string> KnownEdits2(string word)
{

var l = new List<string>();
foreach (var e1 in this.Edits1(word))
foreach (var e2 in Edits1(e1))
if (this.DWORDS.ContainsKey(e2))
l.Add(e2);
return l;
}
List<string> Known(List<string> words)
{

return words.Filter(w => this.DWORDS.ContainsKey(w));
}
public string Correct(string word)
{

var candidateWords = this.Known(DS.List(word));
if (candidateWords.Count == 0)
candidateWords = this.Known(this.Edits1(word));
if (candidateWords.Count == 0)
candidateWords = this.KnownEdits2(word);
if (candidateWords.Count == 0)
candidateWords = DS.List(word);

return this.DWORDS.Max(candidateWords);
}
}

Windows Formuna bir richTextBox ve bir buton ekliyoruz. RichtexBox içindeki kelimeleri parçalayalım. Kelimelerin parçalanacak yerlerini belirlemek için bir dizi oluşturuyorum.
char[] splitChar = new Char[] { ‘ ‘, ‘,’, ‘\n’, ‘.’, ‘?’, ‘!’, ‘\”, ‘’’, ‘:’, ‘;’ };

string[] kelimeler = richTextBox2.Text.Split(splitChar);

//Kelimeler bu noktalardan ayrılacak. kelimeler isimindeki dizimize parçaladığımız kelimeleri atıyoruz.

SpellCorrector Sınıfının bir örneğini oluşturuyoruz.

SpellCorrector den = new SpellCorrector();

 

küçük isimli değişkeni tanımlama sebebi her kelime için iki kere toLower metodunun programın performansını olumsuz etkileyeceğini düşündüğümden tek metod çalışmasını istedim. richTextBox Find metoduyla yaznlış yazılmış kelimeyi buluyoruz ve altını çizili hale getiriyoruz.

foreach (var item in kelimeler)
            {
                kucuk = item.ToLower();
                if (kucuk!= den.Correct(kucuk))
                {
                    richTextBox2.Find(item);
                    //this.richTextBox1.SelectionBackColor = Color.Yellow;
                    Font currFont = richTextBox2.SelectionFont;
                    Font boldUnderFont = new Font(currFont, FontStyle.Underline);
                    richTextBox2.SelectionFont = boldUnderFont;
                }
            }

Kodumuzun tamamı.

 private void button2_Click(object sender, EventArgs e)
        {
            char[] splitChar = new Char[] { ' ', ',', '\n', '.', '?', '!', '\'', '’', ':', ';' }; 
            SpellCorrector den = new SpellCorrector();
            string[] kelimeler = richTextBox2.Text.Split(splitChar);
            string kucuk;

            foreach (var item in kelimeler)
            {
                kucuk = item.ToLower();
                if (kucuk!= den.Correct(kucuk))
                {
                    richTextBox2.Find(item);
                    //this.richTextBox1.SelectionBackColor = Color.Yellow;
                    Font currFont = richTextBox2.SelectionFont;
                    Font boldUnderFont = new Font(currFont, FontStyle.Underline);
                    richTextBox2.SelectionFont = boldUnderFont;
                }
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            SpellCorrector den = new SpellCorrector();
            textBox4.Text = den.Correct(textBox3.Text);
        }

Ek bir konrol daha ekledim. Yanlış kelimeyi yazıp doğru kelimeyi görmek için. İlk metin kutusuna yazdığınız kelimenin önerisini ikinci metin kutusuna yazıyor. Programın bir sonraki adımında altını çizdiğimiz kelimenin üzerinde sağ tuşa basıldığında kelime önerileri görüntüleyecek ve kelimeyi değiştirecek metodu ekleyeceğim.

Bir önceki yazımız olan Visual C# - Rasgele Sayı Üretme başlıklı makalemizde c# ve tips hakkında bilgiler verilmektedir.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir