Did You Mean SoundEx Agorithm

Selamlar;

Bugün google’ın meşhur did you mean mantığından bahsedeceğiz. SoundEx algoritması olarak da bilinen yapı için bir webapi servisi ve kullanıcı arayüzü olarak mvc ile knockoutjs javascript framework’ü kullanıcağız. Database işlemleri için codefirst’den faydalanacağız.

Bu algoritmanın oluşturulmasındaki amaç; telaffuzları benzeşen kelimelerin bu yolla aynı karakter koduna dönüştürülmeleri ve benzer kelimelerin yazımlarında farklılık olsa bile özdeşleştirilmelerinin sağlanmasıdır. SoundEx aslında bir kelimeden fonetik bir kod cikarma yontemidir. İki soundex degeri kiyaslanarak iki kelimenin birbirine ne kadar yakin okundugu cikarilabilir.

Tabi bu algoritmanın kabul görmüş belli kuralları vardır. Şimdi onları inceleyelim:

  1. Karakter katarının ilk harfi alınır.
  2. Eğer ilk harf “a, e, h, i, o, u, w, y” harflerinden herhangi biri değilse, bu harfler string değerden silinir.
  3. Sırasıyla tüm harflere aşağıdaki numaralar atanır.
    b, f, p, v = 1
    c, g, j, k, q, s, x, z = 2
    d, t = 3
    l = 4
    m, n = 5
    r = 6
  4. Eğer numaralandırmada aynı numarayı almış iki ya da daha fazla harf yan yanaysa (ilk işlemden önce) ya da bu harflerin arasında h veya w harfi varsa aynı olanlar çıkartılır.
  5. İlk dört karakteri sonuç olarak döndürülür; eğer sonuç dört karakterden az çıkarsa, dört karaktere tamamlamak amacı ile sona sıfırlar eklenir. (örn. E33 > A330).

Aşağıda bu kurallar üzerinden oluşturulmuş gelen string’in soundex algoritmasına uygun fonetik kodu çıkaran class’ı görüyorsunuz.

ISoundEx

Image Source: https://www.codeproject.com/KB/recipes/soundex/ISoundEx.gif

 SoundExtension.cs:

Aşağıda görüldüğü gibi Webapi projemizde bir aranacak oyunların tam listesini dönen Get() method’u bir de aranacak oyunun soundex algoritmasına tabi tutulacak Post() method’u görülmektedir.

Webapi servis’inde cross domain’i sağlamak için Class’ın başına alttaki attribute’u koymayı unutmuyoruz.

 [EnableCors(origins: “*”, headers: “*”, methods: “*”)]

Get() method’unda oyunların isimlerini string olarak tutacak static bir List<string> kullanılmıştır. Amaç her request’de liste için bir daha database’e gitmemektir. Post() method’unda static List<tblGame> kullanımaktadır. Burada amaç gene database’e olabilecek yükü engellemektir. Database’den çekilen tüm oyun isimleri sıra ile soundex algoritması uygulanıp fonetik kodu çıkarılır. Ve aranan string ifadenin gene soundex algoritması uygulanıp alınan fonetik kodu ile karşılaştırılır. Aynı olan kod’a karşılık gelen oyun ismi geriye döndürülür.

 SoundExController:

 DAL projesine ailt CodeFirst kodları: Aşağıda görüldüğü gibi tblCategory ve tblGames adında 2 tablo vardır. Bu tabloları GameShop adında bir dbcontext altında eşleştirilmiştir.

screen1    screen2    screen3    screen4

Aşağıda knockoutjs için ilgili viewModelimiz tanımlanmıştır. Amaç yukarıdaki örneklerden de anlaşılacağı gibi aranacak oyunun girilmesi ve girilen bu oyunun yazımına en yakın oyun isminin aşağasında 3 karakter girildikten sonra aranıp gösterilmesidir. Bir de en altta aranacak tüm oyun listesi ilk karakter girişi yapıldıktan sonra dolmaktadır. İlgili oyun bulununca listedeki o oyun seçilmektedir. Tüm bu işlemler MVVM design patterin ile knockoutjs yardımı ile yapılmaktadır. Tanımlanan viewModel’de aranacak text searchText property’si olarak tanımlanmıştır. Bulunan oyun ismi result property’si olarak tanımlanmıştır. Başta çekilecek oyun listesi ise listGame observableArray olarak tanımlanmıştır.

<input data-bind=”value: searchText,event: { keyup: send },valueUpdate: ‘afterkeydown'”>

Yukarıda görüldüğü gibi SearchText’in bağladığı property yani viewModel’deki karşılığı data-bind property’si ile searchText olarak gösterilmiştir. Ayrıca keyup eventinde gene viewModel’in bir property’si olan send() function’ı çağrılmaktadır. Bu function’da girilen karakter sayısı 2’den büyükse webapi servisimize post işlemi yapılmaktadır. Ayrıca girilen ilk karakter ise viewModel’in bir diğer property’si olan getList() function’ı çağrılmakta ve tüm oyun listesi data-bind=”options:listGame, value: result” şeklinde yine viewModel’in bir property’si olan listGame’e bağlanmış bir select listesine basılmaktadır.

 Index.cshtml:

İstenirse soundex algorithm’ası Sql tarafından’da uygulanarak çözüme gidilebilir. Örnek query’ler aşağıdadır.

Yukarıdaki örnekde de görüldüğü gibi aranacak text her ne olursa olsun tam olarak doğru yazılmasa da buna en yakın sonuçlar kullanıcıya sunulabilmektedir. Bu da işleri büyük oranda kolaylaştırmaktadır.

Bir sonraki makalede görüşmek üzere hoşçakalın.

Source Code:http://www.borakasmer.com/projects/WebApiSoundEx.rar

Source:

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

2 Cevaplar

  1. Musa dedi ki:

    Merhabalar Hocam,
    yazınızı çok beğendim, kullanmayı düşünüyorum SoundEx algoritmasını. “Get() method’unda oyunların isimlerini string olarak tutacak static bir List kullanılmıştır. Amaç her request’de liste için bir daha database’e gitmemektir.” demişsiniz, bunu kullanmamızın sakıncası var mıdır? Listeye yeni kayıt eklendiğinde ne yapmamız gerekecek bu durumda.

    • borsoft dedi ki:

      Selam Musa,
      Öncelikle teşekkürler.
      Sürekli yeni kayıt eklenecek veya çıkarılacak hatta güncellenecek ise Redis gibi distiributed bir cache, eğer liste çok uzun olacak ise elasticsearch ya da MongoDB, CosmosDB, Firebase gibi Document DBler kullanman daha sağlıklı olabilir. Statick List, senin en başta doldurduğun her client’ın ortak kullandığı, memoryde tutulan bir nesnedir. Ve uygulama kapanana kadar memoryde duru. Bu listeye de eleman sayısı çok olmamak kaydı ile istediğin kelimeyi ekleyip çıkarabilirsin.

      İyi çalışmalar..

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.