İçeriğe geç
academia.sh

Ders 09 / 14

Dizi Fonksiyonları

Süzme, eşleme ve indirgeme fonksiyonları; array_search bulamayınca false döndürmesi; sıfırıncı indeksteki eşleşmenin false ile gevşek karşılaştırmada karışması; boyu uyuşmayan array_combine ve negatif str_repeat çağrısının ValueError vermesi.

Yayın Güncelleme

Bu derste

  • array_filter, array_map ve array_reduce ile bir diziyi süzer, eşler ve tek değere indirger
  • array_search'ün bulamayınca false döndürdüğünü ölçer ve dönüş sınıfına yazar
  • Sıfırıncı indeksteki eşleşmenin gevşek karşılaştırmada bulunamadı sayıldığını ve katı eşitliğin ayrımı yaptığını gösterir
İçindekiler

Çok Boyutlu Diziler dersinde bir yolun kopukluğu null ve E_WARNING olarak duyuldu. Dizi fonksiyonlarında kanal değişiyor: aranan bulunamadığında bir seviye bildirilmiyor, fonksiyon özel bir değer döndürüyor ve bu değerin yorumlanması çağıran kodun işi oluyor. Ders sınıf adlarını önceki derslerdeki anlamıyla kullanır: sessiz, dönüş, uyarı, durdurur.

PHP’nin dizi fonksiyonları geniş bir ailedir ve ders hepsini dolaşmıyor. Ölçülen iki grup var: bir diziyi dönüştüren süzme (filter), eşleme (map) ve indirgeme (reduce) üçlüsü, ve bir diziden eleman arayan fonksiyonlar. Birincisi veri akışının kendisidir, ikincisi ise bir sorunun nereden duyulduğunu en çıplak gösteren yerdir.

Süzme, Eşleme ve İndirgeme

Üç fonksiyon üç ayrı soru sorar. Süzme “hangi elemanlar kalsın”, eşleme “her eleman neye dönüşsün”, indirgeme “hepsi tek bir değere nasıl iner” sorusunu yanıtlar. Aşağıdaki dosya üçünü aynı sayı listesi üzerinde çalıştırıyor.

<?php
// donusum.php — suzme, esleme ve indirgeme
$sayilar = [1, 2, 3, 4, 5, 6];

$ciftler = array_filter($sayilar, fn($n) => $n % 2 === 0);
$kareler = array_map(fn($n) => $n * $n, $sayilar);
$toplam = array_reduce($sayilar, fn($birikim, $n) => $birikim + $n, 0);

echo 'ciftler: ', json_encode($ciftler), "\n";
echo 'kareler: ', json_encode($kareler), "\n";
echo 'toplam: ', $toplam, "\n";
echo 'ciftlerin anahtarlari: ', implode(',', array_keys($ciftler)), "\n";
echo 'yeniden numaralanmis: ', json_encode(array_values($ciftler)), "\n";
ciftler: {"1":2,"3":4,"5":6}
kareler: [1,4,9,16,25,36]
toplam: 21
ciftlerin anahtarlari: 1,3,5
yeniden numaralanmis: [2,4,6]

array_filter tutulan elemanların anahtarlarını korur. ciftler listesinin anahtarları 1, 3, 5 olduğu için json_encode onu bir liste değil bir nesne olarak yazar; array_values anahtarları yeniden numaralar. Bu, İndeksli ve İlişkisel Diziler dersindeki unset davranışının aynısıdır: indeksli görünen bir dizi süzmeden sonra indeksli olmaktan çıkabilir. array_map ise elemanlarla birlikte anahtarları da aynen taşır; bir tek dizi verildiğinde sonuç aynı anahtar kümesini kullanır.

DZ10. array_reduce, geri çağrının ilk parametresini bir birikim (accumulator) değerine bağlar ve başlangıç değeri üçüncü argümandır. Başlangıç değeri verilmezse birikim null ile başlar; boş bir dizi indirgendiğinde sonuç bu durumda null olur. Ders başlangıç değerini her zaman açıkça verir ve boş dizi davranışını ayrıca ölçmez.

Bulunamayan Eleman

Eleman arayan fonksiyonlar sorunu bir uyarıyla değil dönüş değeriyle bildirir. array_search, aranan değeri bulursa anahtarını, bulamazsa false döndürür. Dinleyici bu davranışı kanal sırasıyla sınıflandırıyor; kanal.php aşağıda tam metniyle veriliyor ve çıktı bloğu olmadığı için yalnız diske yazılır.

<?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
// arama.php — bulunamayan eleman ve ValueError
require 'kanal.php';

$gozlemler = [
    'bulunamayan eleman' => fn() => array_search('elma', ['armut', 'ayva']),
    'bulunan eleman'     => fn() => array_search('ayva', ['armut', 'ayva']),
    'ilk eleman'         => fn() => array_search('armut', ['armut', 'ayva']),
    'negatif tekrar'     => fn() => str_repeat('a', -1),
    'boy farkli combine' => fn() => array_combine(['a', 'b'], [1]),
];

foreach ($gozlemler as $ad => $gozlem) {
    [$sinif, $kanit] = dinle($gozlem);
    printf("%-20s%-9s%s\n", $ad, $sinif, $kanit);
}
bulunamayan eleman  donus    sonuc false
bulunan eleman      sessiz   sonuc int 1
ilk eleman          sessiz   sonuc int 0
negatif tekrar      durdurur ValueError
boy farkli combine  durdurur ValueError

İlk satır kursun bulunamayan eleman gözlemidir ve dönüş sınıfındadır: array_search('elma', ['armut', 'ayva']) false döndürdü, hiçbir seviye bildirilmedi, yürütme sürdü. Sorun yalnız dönüş değerine bakan kod tarafından duyulur. İkinci satır başarılı aramayı gösteriyor: bulunan elemanın anahtarı olan 1 sessiz bir sonuçtur. Üçüncü satır sorunun kaynağını hazırlıyor: ilk eleman bulunduğunda dönen anahtar 0 olur.

Son iki satır aynı fonksiyon ailesinin başka bir kanalını gösteriyor. str_repeat('a', -1) ve boyları farklı iki diziyle array_combine çağrısı ValueError fırlatır; sınıf durdurur. Argümanın değeri tipi doğru olsa da kabul edilebilir aralığın dışındaysa fonksiyon sessizce yanlış bir sonuç üretmez, durur. Aynı fonksiyon ailesinde iki farklı kanal bulunur: “bulunamadı” bir dönüş değeridir, “çağrı geçersiz” bir istisnadır.

DZ11. array_combine ve str_repeat yalnız ValueError kanalının örnekleridir. Hangi fonksiyonun hangi koşulda ValueError ya da false verdiği her fonksiyonun kendi belgesinde yazılıdır ve ders onu listelemez; ölçülen, “bulunamadı”nın dönüş, “geçersiz çağrı”nın istisna kanalından geldiğidir.

Sıralama ve Dilimleme

Sıralama fonksiyonlarının hepsi diziyi yerinde değiştirir ve anahtarlara farklı davranır: sort anahtarları atar ve yeniden numaralar, asort değere göre sıralarken anahtarları korur, ksort anahtara göre sıralar. array_slice ise tam sayı anahtarları varsayılan olarak yeniden numaralar.

<?php
// sirala.php — siralama ve dilimlemenin anahtarlara etkisi
$ham = [3 => 'c', 1 => 'a', 2 => 'b'];

$a = $ham;
sort($a);
echo 'sort: ', json_encode($a), "\n";

$b = $ham;
asort($b);
echo 'asort: ', json_encode($b), "\n";

$c = $ham;
ksort($c);
echo 'ksort: ', json_encode($c), "\n";

$d = $ham;
rsort($d);
echo 'rsort: ', json_encode($d), "\n";

echo 'dilim: ', json_encode(array_slice($ham, 1)), "\n";
echo 'dilim, anahtarlar korunur: ', json_encode(array_slice($ham, 1, null, true)), "\n";
echo 'sort dondusu: ', var_export(sort($a), true), "\n";
sort: ["a","b","c"]
asort: {"1":"a","2":"b","3":"c"}
ksort: {"1":"a","2":"b","3":"c"}
rsort: ["c","b","a"]
dilim: ["a","b"]
dilim, anahtarlar korunur: {"1":"a","2":"b"}
sort dondusu: true

sort ve rsort ilişkisel bilgiyi atar; asort ve ksort anahtarı korur ve json_encode bu yüzden onları nesne olarak yazar. array_slice tam sayı anahtarlarını preserve_keys argümanı verilmedikçe yeniden numaralar. Son satır sıralama fonksiyonlarının tuttuğu bir sözleşmeyi gösteriyor: fonksiyonlar diziyi yerinde değiştirir ve geriye true döndürür; sıralanmış kopyayı döndüren bir fonksiyon değildir. $sirali = sort($dizi) yazan kod diziyi sıralar ama $sirali değişkenine true atar.

DZ12. Sıralama fonksiyonlarının kararlılığı (eşit elemanların göreli sırasının korunması) bu derste ölçülmez; ders yalnız anahtarların yazgısını ve dönüş değerini sınar. Karışık tipli diziyi sıralamak dilin karşılaştırma kurallarına bağlıdır ve burada örnek verilmez.

Üyelik Sorgusu

in_array bir değerin dizide bulunup bulunmadığını sorar ve array_search ile aynı gevşek karşılaştırmayı kullanır. Üçüncü argüman true verildiğinde karşılaştırma katı olur.

<?php
// uyelik.php — in_array gevsek ve kati karsilastirma
$sayilar = ['10', '20'];

echo "gevsek, '1e1': ", var_export(in_array('1e1', $sayilar), true), "\n";
echo "kati, '1e1': ", var_export(in_array('1e1', $sayilar, true), true), "\n";
echo "gevsek, 10: ", var_export(in_array(10, $sayilar), true), "\n";
echo "kati, 10: ", var_export(in_array(10, $sayilar, true), true), "\n";
echo "gevsek null, [0]: ", var_export(in_array(null, [0]), true), "\n";
echo "kati null, [0]: ", var_export(in_array(null, [0], true), true), "\n";

$tekrar = ['1', 1, 'a', 'A', 'a'];
echo 'benzersiz: ', json_encode(array_unique($tekrar)), "\n";
gevsek, '1e1': true
kati, '1e1': false
gevsek, 10: true
kati, 10: false
gevsek null, [0]: true
kati null, [0]: false
benzersiz: {"0":"1","2":"a","3":"A"}

Gevşek karşılaştırmada '1e1' dizgisi '10' ile eşit sayılır, çünkü ikisi de sayısal dizgidir ve değerleri 10’dur; katı karşılaştırma ikisini ayırır. Aynı kural 10 tam sayısı ile '10' dizgisi için de geçerlidir. null ile 0 gevşek karşılaştırmada eşittir, katı karşılaştırmada değildir. Bu sonuçlar kötü yazılmış bir koşul değil, gevşek eşitliğin kuralıdır; Programlama Temelleri kursunda (M06/K01) ölçülen zorlama burada bir arama sonucunu etkiliyor. in_array çıktısı yalnızca true ya da false olduğu için yanlış pozitif hiçbir kanaldan duyulmaz: sınıf sessiz. Son satırda array_unique ilk görülen değeri korur ve dizgi gösterimi aynı olan '1' ile 1’i tek sayar; 'a' ile 'A' ayrı kalır.

Eşleme ve Toplamada Sessiz Davranışlar

Eşleme, ters çevirme ve toplama fonksiyonları girdinin biçimi beklenenden farklı olduğunda çoğu zaman bir seviye bildirmez. Aşağıdaki gözlemler aynı dinleyiciyle sınıflanıyor.

<?php
// sessiz.php — esleme, ters cevirme ve toplamada girdi sorunlari
require 'kanal.php';

$gozlemler = [
    'iki dizi, farkli boy' => fn() => array_map(fn($a, $b) => [$a, $b], [1, 2, 3], ['x']),
    'yinelenen deger flip' => fn() => array_flip(['a', 'b', 'a']),
    'yinelenen anahtar'    => fn() => array_combine(['a', 'a'], [1, 2]),
    'sayisal dizgi toplam' => fn() => array_sum(['3', '4']),
    'sayisal olmayan toplam' => fn() => array_sum([1, 'abc']),
    'bos dizi toplam'      => fn() => array_sum([]),
    'bos dizi max'         => fn() => max([]),
    'anahtarla suzme'      => fn() => array_filter(['a' => 1, 'b' => 2], fn($k) => $k === 'a', ARRAY_FILTER_USE_KEY),
];

foreach ($gozlemler as $ad => $gozlem) {
    [$sinif, $kanit] = dinle($gozlem);
    printf("%-23s%-9s%s\n", $ad, $sinif, $kanit);
}

echo 'flip: ', json_encode(array_flip(['a', 'b', 'a'])), "\n";
echo 'combine: ', json_encode(array_combine(['a', 'a'], [1, 2])), "\n";
echo 'map: ', json_encode(array_map(fn($a, $b) => [$a, $b], [1, 2, 3], ['x'])), "\n";
iki dizi, farkli boy   sessiz   sonuc dizi(3)
yinelenen deger flip   sessiz   sonuc dizi(2)
yinelenen anahtar      sessiz   sonuc dizi(1)
sayisal dizgi toplam   sessiz   sonuc int 7
sayisal olmayan toplam uyari    E_WARNING, sonuc int 1
bos dizi toplam        sessiz   sonuc int 0
bos dizi max           durdurur ValueError
anahtarla suzme        sessiz   sonuc dizi(1)
flip: {"a":2,"b":1}
combine: {"a":2}
map: [[1,"x"],[2,null],[3,null]]

array_map iki dizi aldığında kısa olanı null ile tamamlar ve hiçbir seviye bildirmez; [2,null] ve [3,null] çiftleri sessizce üretilir. array_flip ve array_combine yinelenen değer ya da anahtarda son değeri tutar, ilkini sessizce atar: {"a":2,"b":1} ve {"a":2}.

Toplamada sayısal dizgiler sayıya çevrilir ('3' ile '4' toplamı 7), sayısal olmayan bir eleman ise E_WARNING üretir ve toplam yalnız geçerli elemanları sayar. Boş dizide array_sum 0 verir, max ise ValueError ile durur; boş olabilecek bir dizide max çağrılmadan önce count ya da [] !== $dizi ile sınanmalıdır. ARRAY_FILTER_USE_KEY geri çağrıya değer yerine anahtarı verir ve sessiz çalışır.

Sınırlayıcı Ölçüm

Dönüş kanalı yalnız çağıran kod onu doğru okursa çalışır. array_search’ün 0 ve false dönüşleri gevşek eşitlikte aynı değerdir. İki yazım aynı listeyi iki farklı biçimde yorumluyor.

<?php
// ayrim.php — 0 ile false gevsek karsilastirmada ayni degerdir
$liste = ['armut', 'ayva'];

$gevsek = array_search('armut', $liste) == false ? 'bulunamadi' : 'bulundu';
$kati = array_search('armut', $liste) === false ? 'bulunamadi' : 'bulundu';

echo 'gevsek: ', $gevsek, "\n";
echo 'kati: ', $kati, "\n";
echo 'gercekten yok, gevsek: ',
    (array_search('elma', $liste) == false ? 'bulunamadi' : 'bulundu'), "\n";

$karisik = array_filter([1, 0, 2, 0, 3]);
echo 'sifirlar atilir: ', json_encode($karisik), "\n";
echo 'anahtarlar: ', implode(',', array_keys($karisik)), "\n";
gevsek: bulunamadi
kati: bulundu
gercekten yok, gevsek: bulunamadi
sifirlar atilir: {"0":1,"2":2,"4":3}
anahtarlar: 0,2,4

İlk elemanı aratan gevşek karşılaştırma bulunamadi sonucunu verdi, katı karşılaştırma bulundu; gerçekten olmayan elemanda ise gevşek karşılaştırma doğru sonucu verdi. Aynı çağrı, aranan ilk sırada olduğunda yanlış, başka sırada olduğunda doğru yanıt verir ve hiçbir kanal bu farkı bildirmez. Dönüş kanalının ayrım gücü, çağıranın ayrım gücüyle sınırlıdır: 0 ile false ayırt edilmezse bulunan ilk eleman “yok” sayılır.

array_filter ile geri çağrı verilmeden çağrıldığında değeri false’a eşit olan her eleman atılır; 0 da bunlardan biridir. Çıktıdaki anahtarlar 0, 2, 4 olarak kalır: yani hem veri kaybolur hem dizi indeksli olmaktan çıkar ve ikisi de sessizdir. Süzmenin amacı buysa sorun yoktur; amaç yalnız boş değerleri atmaksa 0 beklenen bir değerken de atılmış olur.

Özet

  • array_filter anahtarları korur, array_map anahtarları taşır, array_reduce başlangıç değeriyle tek bir değere iner.
  • Süzmeden sonra dizi indeksli olmaktan çıkabilir; array_values anahtarları yeniden numaralar.
  • array_search bulamayınca false döndürür; bu dersin ölçü sınıfı dönüştür (bulunamayan eleman).
  • Geçersiz argüman değeri (str_repeat('a', -1), boyları farklı array_combine) ValueError fırlatır; sınıf durdurur.
  • İlk eleman bulunduğunda dönen 0, gevşek karşılaştırmada false ile aynıdır; yalnız katı karşılaştırma ikisini ayırır.
  • Geri çağrısız array_filter 0 dahil her false eşdeğeri elemanı sessizce atar.

Sonraki Adım

Bu ders dönüş kanalının ayrım gücünü ölçtü ve 0 ile false karışınca ayrımın çağırana kaldığını gösterdi. Dizgi İşleme dersi aynı kanalın daha sert bir durumunu ölçüyor: iki ayrı sorun aynı dönüş değerini verirse, değer tek başına hangisinin olduğunu söyleyemez.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat