Kayıtlar ve iç içe veri yapıları

Programlama Temelleri dersinde liste içinde sözlük gibi iç içe yapılarla tanıştınız. Bu hafta aynı söz dizimini yeniden öğrenmeyeceğiz. Sorumuz şu:

Aynı kayıt kümesini farklı biçimlerde düzenlersek hangi işlemler kolaylaşır, hangileri zorlaşır?

Kayıt (record), aynı şeye ait bilgilerin bir arada tutulduğu veridir: bir öğrencinin numarası, adı ve notu gibi. Bu derste sınıf yazmadığımız için kayıtları çoğunlukla sözlükle tutacağız. Kayıtları bir araya toplayan dış yapı ise probleme göre değişecek: bazen liste, bazen sözlük.

1 Bu hafta neleri yapabilmelisiniz?

Bölümün sonunda:

  • Bir kaydı sözlükle temsil edebilmeli,
  • Çok sayıda kaydı liste içinde sözlüklerle düzenleyebilmeli,
  • Aynı kayıtlara öğrenci numarası gibi bir kimlikten ulaştıran bir dict oluşturabilmeli,
  • Gruplama için dict + list yapısını kullanabilmeli,
  • Kayıt ekleyebilmeli, güncelleyebilmeli, filtreleyebilmeli ve özetleyebilmeli,
  • Aynı veriyi farklı biçimlerde tutmanın hangi işlemleri kolaylaştırdığını açıklayabilmeli,
  • İç içe yapılarda sığ kopyayı ve aynı nesnenin iki yerden görülmesini fark edebilmelisiniz.

2 Bir kayıt: alan adları neden önemlidir?

Bir öğrenciyi tek tek değişkenlerle tutabiliriz:

number = 102
name = "Bora"
department = "Yazılım"
grade = 78

Ama koda bakınca bu değerlerin aynı öğrenciye ait olduğu anlaşılmaz. Sözlükte bu bağ açıkça görülür:

Sözlükte her değer, ait olduğu alanın (kaydın name, grade gibi bir parçasının) adıyla birlikte durur.

3 Temsil 1: liste içinde kayıtlar

Bir sınıftaki öğrencileri liste içinde sözlüklerle tutabiliriz:

Bu düzen özellikle şu işler için uygundur:

  • Kayıtların sırasını koruma,
  • Bütün kayıtları dolaşma,
  • Filtreleme,
  • Sıralı rapor hazırlama.

flowchart TD
    A["students: list"] --> B["record 1: dict"]
    A --> C["record 2: dict"]
    A --> D["record 3: dict"]
    B --> B1["number"]
    B --> B2["name"]
    B --> B3["grade"]

4 Listede kimliğe göre arama

Öğrenci numarasına göre kayıt bulmak için listeyi dolaşabiliriz:

Bu çözüm yanlış değil. Ama aynı arama binlerce kez yapılacaksa her seferinde listeyi baştan dolaşmak yavaş kalabilir.

5 Temsil 2: kimliğe göre indekslenmiş sözlük

Aynı kayıtları, numarayı anahtar yapan bir sözlükte de tutabiliriz:

Bu temsilde “102 numaralı öğrenci kim?” sorusunun kod karşılığı doğrudan students_by_number[102] olur.

5.1 Aynı veri, farklı güçlü yanlar

Temsil Güçlü olduğu işlem
list[dict] sırayla dolaşma, filtreleme, raporlama
dict[id -> record] kimliğe göre sık erişim
Important

Hangi düzenin daha iyi olduğu probleme bağlıdır. Dış yapıyı seçerken en sık yapılan işleme bakın.

6 Temsil 3: dict + list ile gruplama

Bazen anahtardan tek bir kayda değil, bir kayıt grubuna ulaşmak isteriz. Örneğin öğrencileri bölüme göre gruplayalım:

Burada dış sözlüğün her anahtarı bir bölümün adıdır. O anahtarın değeri olan liste de bölümdeki öğrencileri tutar.

7 Üç temsili birlikte görelim

flowchart LR
    R["Aynı kayıt kümesi"] --> L["list[dict]"]
    R --> I["dict[id → record]"]
    R --> G["dict[group → list[record]]"]
    L --> L1["sıra / filtre / rapor"]
    I --> I1["kimliğe göre erişim"]
    G --> G1["gruba göre erişim"]

Gerçek programlarda aynı kayıtlar bu düzenlerden birkaçında aynı anda tutulabilir.

8 Aynı kayda iki yapıdan ulaşmak

Listedeki kayıtlar için numaraya göre bir sözlüğü sonradan da oluşturabiliriz:

Neden listedeki kayıt da değişti? Çünkü students listesi ile by_number sözlüğü aynı öğrenci sözlüğünü gösteriyor.

Bu işe yarayabilir: aynı kaydı kopyalamadan ona iki farklı yoldan ulaşırız. Ama bağımsız bir kopya bekliyorsak hataya yol açabilir.

9 Filtreleme kalıbı

Belirli koşula uyan kayıtları yeni bir listede toplayalım:

Filtrelerken bütün kayıtlara bakmak gerektiği için list[dict] uygun bir seçimdir.

10 Alıştırma: düşük stoklu ürünler

stock değeri 10’dan küçük ürünlerin adlarını low_stock listesine ekleyin.

Beklenen çıktı:

['Defter', 'Silgi']

if product["stock"] < 10: koşulundan sonra low_stock.append(...) kullanın.

for product in products:
    if product["stock"] < 10:
        low_stock.append(product["name"])

11 Alıştırma: kimliğe göre indeks oluştur

Aşağıdaki ürünleri, code alanı anahtar olacak biçimde by_code sözlüğüne yerleştirin.

Sözlüğün anahtarı product["code"], değeri ise product kaydının kendisi olabilir.

for product in products:
    by_code[product["code"]] = product

12 Özetleme

Kayıtlardaki sayısal alanları özetlemek için biriktirici kalıbını kullanabiliriz:

Burada toplamın kendisinden çok kalıp önemli: bütün kayıtları dolaşıp her birinden aynı alanı alıyoruz.

13 İç içe yapıları okurken adım adım düşünün

Şu ifadeyi inceleyelim:

students[1]["courses"][0]

Bunu tek seferde değil adım adım okuyun:

  1. students[1] → ikinci öğrenci kaydı,
  2. ["courses"] → o kaydın ders listesi,
  3. [0] → ilk ders.

Böyle okumak, iç içe yapılarda yanlış indeks ya da yanlış anahtar yazma hatalarını azaltır.

14 Sığ kopya tekrar karşımıza çıkıyor

.copy() yalnız dıştaki sözlüğü kopyalar; içteki tags listesi iki kayıt arasında ortak kalır. Bu, 2. haftada gördüğümüz sığ kopyanın kayıtlardaki karşılığıdır.

15 Küçük karar çalışması

Aynı öğrenci verisi için aşağıdaki ihtiyaçların her birinde hangi düzeni seçerdiniz?

  1. Bütün öğrencileri kayıt sırasıyla ekranda göstermek.
  2. Öğrenci numarasına göre saniyede çok sayıda sorgu yapmak.
  3. Bölüm adına göre o bölümdeki öğrencilerin tamamına ulaşmak.

Seçenekler:

A. list[dict]
B. dict[number -> record]
C. dict[department -> list[record]]

Yanıtınıza yalnızca yapının adını değil, hangi işlemi kolaylaştırdığını da yazın.

16 Bölüm özeti

  • Bir kaydı sözlükle tutabiliriz.
  • list[dict], çok sayıda kaydı sırayla dolaşmak, filtrelemek ve raporlamak için uygundur.
  • Aynı kayıtları dict[id -> record] biçiminde indekslemek kimliğe göre sık erişimi kolaylaştırır.
  • dict[group -> list[record]] gruplama problemlerine uygundur.
  • Aynı kayıt nesnesini birden çok koleksiyon gösterebilir.
  • Düzeni söz dizimine göre değil, yapılacak işlemlere göre seçeriz.
  • İç içe yapılarda sığ kopyaya dikkat edin: içteki nesneler ortak kalır.

17 Kendinizi kontrol edin

  1. list[dict] hangi işlemler için uygundur?
  2. Öğrencilere numarayla çok sık erişmek gerekiyorsa dış yapıyı nasıl değiştirirsiniz?
  3. Öğrencileri bölüme göre gruplamak için hangi yapıları birlikte kullanırsınız?
  4. students listesi ile by_number sözlüğü aynı kayıt nesnesini gösteriyorsa birindeki değişiklik neden diğerinde görünür?
  5. Filtreleme için neden çoğu zaman bütün kayıtları dolaşmak gerekir?
  6. Sığ kopyası alınmış bir sözlüğün içindeki liste neden iki kopyada ortak kalır?
Back to top