Eşleme Tabloları
Eşleme tabloları, üst düzey dillerin hepsinde bulunan veri yapılarıdır. Onları, program içine gömülen minik veri tabanları olarak düşünülebilirsiniz. Programlarda çok kullanılan ve çok hızlı veri yapılarıdır.
Dizileri, "elemanları yan yana duran topluluk" olarak tanımlamış ve elemanlarına indeksle erişildiğini görmüştük. Örneğin haftanın günlerinin isimlerini tutan bir dizi şöyle tanımlanabilir:
string[] günİsimleri =
[ "Pazartesi", "Salı", "Çarşamba", "Perşembe",
"Cuma", "Cumartesi", "Pazar" ];
ve, belirli bir günün ismi o diziyi kullanarak şöyle yazdırılabilir:
writeln(günİsimleri[1]); // "Salı" yazar
Diziler elemanlara numara ile (indeksle) erişmeye çok uygundurlar, ama bunun tersini yapamazlar. Örneğin elimizde "Salı" dizgisi bulunduğunda onun haftanın 1 numaralı günü olduğunu söyleyemezler (indekslerin 0'la başladıklarını hatırlayın):
writeln(günSıraları["Salı"]); // ← derleme HATASI
O satırda "1" yazmayı umuyoruz ama derleme hatası oluşuyor; çünkü dizilerde indeks olarak yalnızca tamsayı türler kullanılabilir; "Salı" gibi dizgiler indeks olamazlar.
Eşleme tablolarının kullanışlılığı işte bu gibi durumlarda ortaya çıkar. Eşleme tabloları, elemanlara yalnızca numara ile değil, herhangi bir türle erişilen veri yapılarıdır.
Görevleri; herhangi bir indeks türündeki bir değeri, herhangi başka bir türdeki değere eşlemektir.
Çok hızlı ama sırasız
Eşleme tabloları arka planda hash table veri yapısını kullandıkları için algoritma karmaşıklığı açısından dizilerden geri kalmazlar: son derece hızlı topluluklardır. Bunun anlamı, içlerindeki eleman sayısından bağımsız olarak, hemen her zaman için sabit zamanda erişim sağlamalarıdır.
Bu kadar hızlı çalışmalarının bedeli, içlerindeki elemanların sıraları konusunda bir şey bilinemiyor olmasıdır. Elemanların ne dizilerdeki gibi yan yana olduklarını, ne de örneğin küçükten büyüğe doğru sıralandıklarını söyleyebiliriz.
Tanımlama
Eşleme tablosu tanımı, dizi tanımına çok benzer. Tek farkı, köşeli parantezler içine dizinin uzunluğu yerine, dizinin indeks türünün gelmesidir. Söz dizimi, eleman_türü[indeks_türü] şeklindedir. Örneğin türü string olan gün isminden, türü int olan gün sıra numarasına eşleme yapan bir eşleme tablosu şöyle tanımlanır:
int[string] günSıraları;
Eşleme tablolarının en kullanışlı taraflarından birisi; indeks ve eleman türü olarak, daha sonra öğreneceğimiz yapı ve sınıf türleri de dahil olmak üzere, her türün kullanılabilmesidir.
Dinamik dizilerinki gibi, eşleme tablolarının boyları da tanımlandıkları zaman belirlenmez; tablo, otomatik olarak büyür.
Atama
Elemanı indeks değeri ile atamak; eşleme bilgisinin kurulması ve tablonun otomatik olarak büyümesi için yeterlidir:
günSıraları["Pazartesi"] = 0; günSıraları["Salı"] = 1;
İlkleme
Gün sıraları kavramında olduğu gibi, eşleme bilgisi bazen tablo kurulduğu sırada bilinir. Eşlemeleri teker teker atayarak kurmak yerine, bu bilgiyi tabloyu tanımladığımız zaman da verebiliriz. Tablo, dizi söz diziminde olduğu gibi ilklenir; indeks değerleri ile eleman değerleri arasına : karakteri yazılır:
int[string] günSıraları = [ "Pazartesi":0, "Salı":1, "Çarşamba":2, "Perşembe":3, "Cuma":4, "Cumartesi":5, "Pazar":6 ]; writeln(günSıraları["Salı"]); // "1" yazar
Eleman silme
Buradaki kullanımında "çıkart, at" anlamına gelen .remove işlevi ile:
günSıraları.remove("Salı"); writeln(günSıraları["Salı"]); // ← çalışma zamanı HATASI
Son satır, tabloda bulunmayan bir elemana eriştiği için çalışma zamanında bir hata atılmasına neden olur.
Eleman sorgulama
Tabloda bulunmayan bir elemana erişmek, bir hata atılmasına neden olacağı için; sorgulamak için in işleci kullanılır. Bu kullanım, "içinde var mı?" sorusunu yanıtlar:
if ("mor" in renkKodları) { // evet, renkKodları'nda "mor" indeksli eleman varmış } else { // hayır, yokmuş... }
Nitelikler
.lengthtablodaki eleman sayısı.keystabloda bulunan bütün indeksler, dinamik dizi olarak.valuestabloda bulunan bütün elemanlar, dinamik dizi olarak.rehashancak gerektiği durumda, tablonun daha etkin çalışmasını sağlayabilir; tablo erişimini hızlandırmak için, örneğin çok sayıda eleman giriş işleminin sonunda, tablonun asıl kullanımı başlamadan önce bu nitelik çağrılabilir.sizeoftablonun referansının büyüklüğüdür (tablonun kullanımıyla doğrudan bir ilgisi yoktur ve çoğu ortamda 8'dir)
Örnek
Girilen rengin İngilizcesini veren bir program şöyle yazılabilir:
import std.cstream; void main() { string[string] renkler = [ "siyah" : "black", "beyaz" : "white", "kırmızı" : "red", "yeşil" : "green", "mavi" : "blue", ]; dout.writefln("Ben bu ", renkler.length, " rengin İngilizcelerini öğrendim: ", renkler.keys); dout.writef("Haydi sor: "); char[] türkçesi; din.readf(&türkçesi); if (türkçesi.idup in renkler) { dout.writefln( "İngilizce'de \"%s\"", renkler[türkçesi]); } else { dout.writefln("Onu bilmiyorum..."); } }
Problemler
- Kullanmakta olduğunuz bir eşleme tablosunu nasıl bütünüyle boşaltabilirsiniz? En az üç yöntem düşünülebilir:
- bir döngü içinde teker teker silmek
- boş bir tablo atamak
- bir öncekine benzer olarak, tablonun
.initniteliğinden yararlanmak
Not: Bu niteliği ilk defa duyuyorsunuz: her türün.initniteliği, o türün ilk değeri olarak kullanılan değerdir; örneğin:sayı = int.init; // int için 0 olur
- Dizilerde olduğu gibi, eşleme tablolarında da her indekse karşılık tek bir eleman bulunabilir. Baştan bunun kısıtlayıcı olduğu düşünülebilir.
Her öğrenci için birden fazla not tutmak istiyor olalım. Örneğin "emre" için 90, 85, 95, vs. notları barındırmak isteyelim.
Bir eşleme tablosu kullanmak, notlara notlar["emre"] şeklinde öğrencinin ismiyle erişme konusunda yardımcı olur. Ancak, notları tabloya aşağıdaki şekilde yerleştirmek işe yaramaz:
int[string] notlar; notlar["emre"] = 90; notlar["emre"] = 85; // ← Olmaz: birincinin üstüne yazar
Ne yapabilirsiniz? Her öğrenci için birden fazla not tutabilen bir eşleme tablosu tanımlayın.
D.ershane
Forum
Wiki
Projeler
Tanıtım
İletişim
Hakları