Ders 07 / 14
İndeksli ve İlişkisel Diziler
Tek bir dizi yapısının hem liste hem sözlük olarak kullanılması; '1', 1 ve true anahtarlarının tek anahtara inmesi; ondalık anahtarın kesilmesi; normalleşmenin yalnız kanonik ondalık tam sayı dizgilerine uygulanması.
Yayın Güncelleme
Bu derste
- Tek dizi yapısının hem indeksli hem ilişkisel kullanımını ve eklenme sırasının korunmasını örnekle gösterir
- '1', 1 ve true anahtarlarının tek anahtara inmesini sessiz kanal olarak ölçer ve sınıflandırır
- Anahtar normalleşmesinin hangi dizgilere uygulandığını ölçerek kanonik ondalık tam sayı kuralına bağlar
İçindekiler
Fonksiyonlar dersi, fazladan verilen bir argümanın hiçbir sinyal vermeden atıldığını ölçtü: iki_topla(1, 2, 3) sonuç olarak 3 üretti ve çağıran tarafa hiçbir haber gitmedi. Bu ders aynı sessizliğin bir veri yapısında da çıkıp çıkmadığını soruyor: aynı diziye farklı yazımlarla verilen anahtarlar birbirine karışırsa bunu kim söylüyor? Kursun ölçü sorusu değişmiyor — bu sorun hangi kanaldan duyuluyor — ve sınıf adları bu derste yalnız kullanılıyor: sessiz, dönüş, uyarı, durdurur.
PHP’de array tek bir yapıdır ve iki kullanımı karşılar. Anahtarları ardışık tam sayılar olan dizi indeksli dizi (indexed array) olarak okunur; anahtarları dizgi olan dizi ilişkisel dizi (associative array) olarak. İkisi arasında tip farkı yoktur, fark yalnız anahtarların ne olduğundadır. Programlama Temelleri kursunda (M01/K02) kurulan değişken ve tip kavramları burada olduğu gibi geçerlidir; yeni olan, anahtarın yazıldığı gibi saklanmayıp bir kuraldan geçmesidir.
Tek Yapıda İki Kullanım
Aşağıdaki dosya aynı yapıyı üç biçimde kullanıyor: liste, sözlük ve ikisinin karışımı. Her dizinin anahtarları array_keys ile yan yana basılıyor.
<?php // diziler.php — ayni yapi hem liste hem sozluk olarak kullanilir $liste = ['elma', 'armut', 'ayva']; $liste[] = 'nar'; $kisi = ['ad' => 'Ada', 'yas' => 36]; $kisi['sehir'] = 'Izmir'; $karisik = ['bir', 'iki', 'ozel' => 'x']; $karisik[] = 'uc'; $sirali = [3 => 'c', 1 => 'a']; $sirali[] = 'd'; $silinmis = ['x', 'y', 'z']; unset($silinmis[1]); $silinmis[] = 'w'; echo 'liste: ', implode(',', array_keys($liste)), "\n"; echo 'kisi: ', implode(',', array_keys($kisi)), "\n"; echo 'karisik: ', implode(',', array_keys($karisik)), "\n"; echo 'sirali: ', implode(',', array_keys($sirali)), "\n"; echo 'silinmis: ', implode(',', array_keys($silinmis)), "\n"; echo 'liste mi: ', var_export(array_is_list($liste), true), ' ', var_export(array_is_list($kisi), true), ' ', var_export(array_is_list($silinmis), true), "\n";
liste: 0,1,2,3 kisi: ad,yas,sehir karisik: 0,1,ozel,2 sirali: 3,1,4 silinmis: 0,2,3 liste mi: true false false
Köşeli parantezle ekleme, anahtar vermeden eleman ekler ve PHP o elemana bir sonraki tam sayı anahtarı verir: karışık dizide ozel anahtarından sonra eklenen 'uc' değeri 2 anahtarını aldı. sirali satırı sıranın anahtara değil eklenmeye bağlı olduğunu gösteriyor: 3 anahtarı önce yazıldığı için önce geliyor, ardından gelen 1 ve eklenen 4. silinmis satırı bir eleman silindiğinde anahtarların yeniden numaralanmadığını gösteriyor; array_is_list bu yüzden false dönüyor. İndeksli görünen bir dizi, bir unset’ten sonra indeksli olmaktan çıkabilir ve bunu hiçbir şey bildirmez.
DZ1. Bu derste “sıra”, elemanların eklenme sırasıdır; foreach dizi üzerinde bu sırayla dolaşır. Sıranın anahtar değerinden bağımsız olduğu yukarıdaki koşumla gösterilir ve sayısal sıralama gerektiren her iş açıkça sıralama yapar. Dizinin başka bir değişkene atanınca kopyalanıp kopyalanmadığı ise bu dersin sorusu değildir: o, M11/K03’te ölçülen “bu değişikliği kim görüyor” sorusudur ve burada sorulmaz.
Anahtar Normalleşmesi
Bir dizi anahtarı yalnız int ya da string olabilir. Başka bir tipte yazılan anahtar bu ikisinden birine normalleşir (normalization): true anahtarı 1 olur, ondalık bir sayı tam sayıya kesilir, ondalık tam sayı biçimindeki bir dizgi tam sayıya dönüşür. Tanım bundan ibarettir; ilginç olan, bu dönüşümün yazım düzeyinde görünmemesidir. Aşağıdaki dosya kanal.php’yi çeker; kanal sınıflandırıcısı kursun ortak yardımcısıdır ve bu derste kesiti kullanılıyor.
<?php // kanal.php — bir sorunun hangi kanaldan duyuldugunu siniflandiran yardimcilar // Yakalanan uyarilarin seviye adlari burada birikir; ileti metni tutulmaz. $GLOBALS['duyulan_uyarilar'] = []; set_error_handler(function (int $seviye): bool { $adlar = [E_WARNING => 'E_WARNING', E_NOTICE => 'E_NOTICE', E_DEPRECATED => 'E_DEPRECATED']; $GLOBALS['duyulan_uyarilar'][] = $adlar[$seviye] ?? 'E_' . $seviye; return true; }); // Degeri tipiyle birlikte kisa bir metne cevirir. function yaz(mixed $deger): string { return match (true) { $deger === null => 'null', is_bool($deger) => $deger ? 'true' : 'false', is_array($deger) => 'dizi(' . count($deger) . ')', default => get_debug_type($deger) . ' ' . $deger, }; } // Isi calistirir ve sorunun hangi kanaldan duyuldugunu sirayla sorar: // once firlatma, sonra uyari, sonra false/null donus; hicbiri yoksa sessiz. function dinle(callable $is): array { $GLOBALS['duyulan_uyarilar'] = []; try { $sonuc = $is(); } catch (Throwable $hata) { return ['durdurur', get_class($hata)]; } if ($GLOBALS['duyulan_uyarilar']) { $seviyeler = implode(',', array_unique($GLOBALS['duyulan_uyarilar'])); return ['uyari', $seviyeler . ', sonuc ' . yaz($sonuc)]; } if ($sonuc === false || $sonuc === null) { return ['donus', 'sonuc ' . yaz($sonuc)]; } return ['sessiz', 'sonuc ' . yaz($sonuc)]; } // Kodu ayri bir PHP yurutmesinde calistirir; cikis kodu 255 ise yurutme durmustur. function ayri_yurut(string $kod): array { exec('php -d display_errors=0 -r ' . escapeshellarg($kod) . ' 2>&1', $satirlar, $cikis); $sinif = $cikis === 255 ? 'durdurur' : 'sessiz'; return [$sinif, 'cikti ' . count($satirlar) . ' satir, cikis ' . $cikis]; }
<?php // normallesme.php — farkli yazilan anahtarlarin tek anahtara inmesi require 'kanal.php'; $gozlemler = [ 'uc yazim, tek anahtar' => fn() => ['1' => 'a', 1 => 'b', true => 'c'], 'ondalik anahtar' => function () { $anahtar = 1.7; return [$anahtar => 'x']; }, ]; foreach ($gozlemler as $ad => $gozlem) { [$sinif, $kanit] = dinle($gozlem); printf("%-22s%-9s%s\n", $ad, $sinif, $kanit); } $dizi = ['1' => 'a', 1 => 'b', true => 'c']; echo 'kalan anahtar: ', array_key_first($dizi), ', deger: ', $dizi[1], "\n";
uc yazim, tek anahtar sessiz sonuc dizi(1) ondalik anahtar uyari E_DEPRECATED, sonuc dizi(1) kalan anahtar: 1, deger: c
İlk satır kursun anahtar normallesmesi gözlemidir ve sessiz sınıftadır. '1', 1 ve true üç ayrı yazımdır; üçü de 1 anahtarına indi, dizide tek eleman kaldı ve o elemanın değeri son yazılan 'c' oldu. dinle() soruyu sırayla sordu: fırlatma yok, uyarı bildirilmedi, sonuç false ya da null değil; geriye sessizlik kalıyor. Sorun yalnız sonuca bakılarak görülebilir — burada dizi(1) yerine dizi(3) beklemiş biri, eksik iki elemanı hiçbir yerden duymadı. Bu, fazla argümanın atılmasıyla aynı sınıftır; fark, burada atılanın bir değer olması ve anahtarın onu ezmesidir.
İkinci satır aynı mekanizmanın başka bir yüzü: 1.7 anahtarı 1’e kesildi ve bu kez bir hata seviyesi bildirildi. E_DEPRECATED kullanımdan kaldırma seviyesidir ve yürütme sürüyor; sınıf bu yüzden uyarı. true ve '1' değeri kaybetmeden 1’e iniyor, 1.7 ise ondalık kısmı atıyor. Sessizliğin sınırını bilgi kaybı çiziyor: bilgi kaybeden dönüşüm duyuruluyor, kayıpsız görünen dönüşüm duyurulmuyor.
DZ2. E_DEPRECATED bu derste uyarı sınıfına yazılır, çünkü çekirdeğin tanımı yalnız iki şey soruyor: bir hata seviyesi bildirildi mi, yürütme sürdü mü. Seviyenin anlamı — davranışın ileride değişebileceği — sınıfı değiştirmez; yalnız bu uyarının gelecekte bir durdurur olabileceğini söyler. Ders bu geleceği ölçmüyor.
Anahtar Tipleri ve Birleştirme
Normalleşme yalnız dizgi ile tam sayı arasında işlemez; mantıksal değerler, boş değer ve ondalık sayılar da anahtar yerine yazılabilir. Hangi anahtara indiklerini ölçmek için her aday bir değişkende tutuluyor ve tek elemanlı bir dizinin anahtarı olarak kullanılıyor.
<?php // tipler.php — farkli tipteki adaylarin indigi anahtar require 'kanal.php'; function anahtar_of(mixed $aday): string { $dizi = [$aday => 'x']; return var_export(array_key_first($dizi), true); } $adaylar = [ 'null' => null, 'false' => false, 'true' => true, 'tam ondalik' => 2.0, 'bos dizgi' => '', ]; foreach ($adaylar as $ad => $aday) { [$sinif, $kanit] = dinle(fn() => anahtar_of($aday)); printf("%-12s%-9s%s\n", $ad, $sinif, $kanit); } [$sinif, $kanit] = dinle(function () { $bos = null; return count([$bos => 'a', '' => 'b']); }); echo 'null ve bos dizgi birlikte: ', $sinif, ' ', $kanit, "\n";
null uyari E_DEPRECATED, sonuc string '' false sessiz sonuc string 0 true sessiz sonuc string 1 tam ondalik sessiz sonuc string 2 bos dizgi sessiz sonuc string '' null ve bos dizgi birlikte: uyari E_DEPRECATED, sonuc int 1
null anahtarı boş dizgiye iner ve E_DEPRECATED bildirir (uyarı); false 0’a, true 1’e, kesri olmayan 2.0 ise 2’ye iner ve bu üçü ile boş dizgi sessizdir. Son satır sonucu bağlıyor: null ile '' aynı anahtardır ve ikisini birlikte yazan bir dizi tek eleman taşır. Bu dönüşümlerin çoğunda bilgi kaybı yok gibi görünür; oysa null ile boş dizgiyi ayrı veri olarak taşıyan bir kaynak, diziye girdiğinde ayrımı yitirir. Kesri olan ondalık sayı ise önceki bölümde ölçüldüğü gibi uyarı ile kesilir.
DZ3. Tablodaki beş aday dilin dönüşüm kuralını örnekler; anahtar olarak geçerli olmayan tipler (başka bir dizi, bir nesne) bu dersin dışındadır ve burada ölçülmez. Ders hangi tipin hangi anahtara indiğini yazılı kuraldan değil, koşturulan çıktıdan okur.
İki dizi birleştirilirken anahtarların çakışması ikinci bir normalleşme noktasıdır. Aynı iki diziye üç ayrı birleştirme uygulandığında anahtarların yazgısı da üç ayrı çıkar.
<?php // birlestir.php — ayni iki diziyi uc farkli yolla birlestirmek $a = ['ad' => 'Ada', 5 => 'x', 6 => 'y']; $b = ['ad' => 'Can', 5 => 'z']; echo 'toplama: ', json_encode($a + $b), "\n"; echo 'array_merge: ', json_encode(array_merge($a, $b)), "\n"; echo 'array_replace: ', json_encode(array_replace($a, $b)), "\n"; echo 'yayma: ', json_encode([...$a, ...$b]), "\n"; echo 'anahtarlar: ', implode(',', array_keys(array_merge($a, $b))), "\n";
toplama: {"ad":"Ada","5":"x","6":"y"}
array_merge: {"ad":"Can","0":"x","1":"y","2":"z"}
array_replace: {"ad":"Can","5":"z","6":"y"}
yayma: {"ad":"Can","0":"x","1":"y","2":"z"}
anahtarlar: ad,0,1,2
Toplama işleci sol dizinin değerini korur ve yalnız sağdaki yeni anahtarları ekler: ad anahtarı 'Ada' kaldı, 5 anahtarı 'x' kaldı. array_merge dizgi anahtarlarında sağ değeri alır ('Can') ama tam sayı anahtarları yeniden numaralar: 5 ve 6 anahtarları kayboldu, iki tarafın üç elemanı da korunarak 0, 1, 2 anahtarlarına indi. array_replace ise tam sayı anahtarlarına dokunmadan sağ değeri yazar. Yayma sözdizimi array_merge ile aynı sonucu verir. Dört yazım, aynı iki dizi için üç farklı sonuç üretti ve hiçbiri bir seviye bildirmedi: sınıf sessiz.
DZ4. array_merge ile toplama arasındaki fark bu derste yalnız anahtar çakışmasıyla ölçülür. Hangisinin hızlı ya da hangisinin tercih edilmesi gerektiği ölçülmez; ders bir fonksiyonu diğerine üstün tutmaz, yalnız aynı girdinin farklı sonuç verdiğini gösterir.
Anahtar Var mı Sorusu
Bir anahtarın dizide bulunup bulunmadığı iki ayrı soruyla sorulabilir ve sorular aynı cevabı vermez. isset anahtarın var ve değerinin null olmadığını sorar, array_key_exists yalnız anahtarın var olup olmadığını, ?? ise değer yoksa ya da null ise yedeği verir.
<?php // varmi.php — isset, array_key_exists ve ?? farki $veri = ['dolu' => 'x', 'bos' => null, 'sifir' => 0]; foreach (['dolu', 'bos', 'sifir', 'yok'] as $anahtar) { printf( "%-6s isset=%-5s var=%-5s birlesim=%s\n", $anahtar, var_export(isset($veri[$anahtar]), true), var_export(array_key_exists($anahtar, $veri), true), var_export($veri[$anahtar] ?? 'yedek', true) ); }
dolu isset=true var=true birlesim='x' bos isset=false var=true birlesim='yedek' sifir isset=true var=true birlesim=0 yok isset=false var=false birlesim='yedek'
bos satırı ayrımı gösteriyor: anahtar var, değer null. isset bunu yok sayar, array_key_exists var sayar, ?? yedeği verir. sifir satırında üçü de değeri var kabul eder; 0 boş değer değildir. yok satırında anahtarın gerçekten bulunmadığı durumda isset ve array_key_exists ikisi de false verir. Üç sorgunun üçü de uyarı üretmeden bir bool ya da yedek değer döndürdü; bir anahtarın eksikliğini uyarıdan duymak isteyen kod yalın okumayı seçmek zorundadır, ve yalın okuma bir sonraki derste ölçülür.
Sınırlayıcı Ölçüm
Normalleşme her dizgiye uygulanmaz. Hangi dizgilerin tam sayı anahtara dönüştüğünü ölçmek için dizgi anahtarları tek tek denenebilir: her biri tek elemanlı bir dizinin anahtarı yapılıyor ve array_key_first o anahtarın tipini söylüyor.
<?php // sinir.php — hangi dizgi anahtarlar tam sayiya donusur $adaylar = ['0', '1', '-1', '01', '1.5', '-0', ' 1']; foreach ($adaylar as $aday) { $dizi = [$aday => 'x']; $anahtar = array_key_first($dizi); printf("%-6s%s\n", "'" . $aday . "'", get_debug_type($anahtar)); } $iki = ['1' => 'a', '01' => 'b']; echo 'iki yazim, eleman sayisi: ', count($iki), "\n";
'0' int '1' int '-1' int '01' string '1.5' string '-0' string ' 1' string iki yazim, eleman sayisi: 2
Kural çıktıdan okunuyor: yalnız ondalık, kanonik tam sayı biçimindeki dizgiler tam sayı anahtara dönüşür. '1' ve '-1' tam sayı olur; baştaki sıfır ('01'), ondalık nokta ('1.5'), eksi işaretli sıfır ('-0') ve boşluk (' 1') taşıyan dizgiler dizgi kalır. Bu ayrım, önceki bölümdeki sessizliğin sınırını çiziyor: '1' ile 1 aynı anahtarsa '01' farklı bir anahtardır ve son satırdaki iki yazım bu kez iki eleman bırakıyor. Normalleşme “aynı sayıyı farklı yazanları birleştirme” kuralı değil, “kanonik yazımı tam sayıya çevirme” kuralıdır; aynı sayıyı iki biçimde yazan bir veri kaynağı, dizide iki ayrı eleman üretir ve bunu da hiçbir sinyal bildirmez.
DZ5. Bu bölümdeki tipler ve anahtarlar dilin kendi kuralının sonucudur; tek bir sayıya değil sınıfa dayanır. Ölçülen yedi aday dilin belgelediği sınıfı örnekler ve tamamlayıcı olmayı iddia etmez. Bir dizgi anahtar tam sayıya dönüşmüyorsa, bunun nedeni o yapının kanonik ondalık biçimde olmamasıdır; ders başka bir tabana ya da çok büyük tam sayılara geçmiyor.
Özet
- PHP’de
arraytek yapıdır: anahtarları ardışık tam sayılar olan dizi indeksli, dizgi anahtarlı olan ilişkisel dizi olarak okunur; sıra eklenme sırasıdır. unsetanahtarları yeniden numaralamaz; indeksli görünen diziarray_is_listile sınanmadıkça indeksli kalıp kalmadığı bildirilmez.'1',1vetruetek anahtara normalleşir ve dizide tek eleman kalır; bu dersin ölçü sınıfı sessizdir (anahtar normallesmesi).1.7gibi ondalık anahtar kesilir veE_DEPRECATEDbildirilir; bilgi kaybeden dönüşüm uyarı kanalından duyulur.- Normalleşme yalnız ondalık, kanonik tam sayı biçimindeki dizgilere uygulanır;
'01','1.5've'-0'dizgi kalır.
Sonraki Adım
Bu ders tek düzeyli bir dizinin anahtarlarını ölçtü. Bir dizinin elemanı başka bir dizi olduğunda anahtar tek değil bir yol olur, ve yolun bir halkası eksikse null gelir. Çok Boyutlu Diziler dersi eksik bir iç anahtarın hangi kanaldan duyulduğunu ve aynı yola yazmanın neden başka bir kanaldan duyulduğunu ölçüyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.