5-bo‘lim

Massivlar

PHP massivi - tartiblangan xarita; indeksli va assotsiativ massivlar, saralash, filtrlash va ko'p o'lchovli tuzilmalar.

🕑 12 daqiqa o‘qish 📄 632 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Ikki ko'rinish
  2. Qo'shish va o'chirish
  3. Qidirish va tekshirish
  4. map, filter, reduce
  5. Saralash
  6. Ko'p o'lchovli massivlar
  7. Xulosa

PHP da massiv - oddiy ro'yxat emas. U tartiblangan xarita: kalit-qiymat juftliklari, lekin qo'shilish tartibini ham saqlaydi.

Aynan shuning uchun PHP da massiv bir vaqtning o'zida ro'yxat, lug'at, stek va navbat vazifasini bajaradi.

Ikki ko'rinish #

PHP
// Har bir misol qat'iy turlar rejimida ishlaydi.
PHP
// Indeksli - kalitlar 0 dan boshlanadi
$shaharlar = ["Toshkent", "Namangan", "Samarqand"];

// Assotsiativ - kalitlar o'zingiz beradigan satrlar
$aholi = [
    "Toshkent"   => 2900000,
    "Namangan"   => 650000,
    "Samarqand"  => 560000,
];

echo "Indeksli massiv:\n";
foreach ($shaharlar as $kalit => $qiymat) {
    echo "  [{$kalit}] => {$qiymat}\n";
}

echo "\nAssotsiativ massiv:\n";
foreach ($aholi as $shahar => $son) {
    printf("  %-12s %12s\n", $shahar, number_format($son, 0, ",", " "));
}

echo "\n";
echo "Aralash ham mumkin (lekin tavsiya etilmaydi):\n";
$aralash = ["a", "kalit" => "qiymat", "b"];
foreach ($aralash as $k => $v) {
    echo "  " . var_export($k, true) . " => {$v}\n";
}
Natija
Indeksli massiv:
  [0] => Toshkent
  [1] => Namangan
  [2] => Samarqand

Assotsiativ massiv:
  Toshkent        2 900 000
  Namangan          650 000
  Samarqand         560 000

Aralash ham mumkin (lekin tavsiya etilmaydi):
  0 => a
  'kalit' => qiymat
  1 => b
Ichkarida hammasi bitta tur

PHP da ["a", "b"] va [0 => "a", 1 => "b"] - bir xil narsa. Indeksli massiv shunchaki kalitlari butun son bo'lgan assotsiativ massiv.

Buni tekshirish oson:

PHP
var_dump(["a", "b"] === [0 => "a", 1 => "b"]);  // true

Bu qulaylik, lekin tuzoq ham: massivdan element o'chirsangiz, kalitlar qayta raqamlanmaydi:

AmalNatija kalitlari
["a","b","c"]0, 1, 2
unset($m[1])0, 2
array_values($m)0, 1

Agar natijani JSON ga aylantirsangiz, birinchi holat massiv (["a","c"]), ikkinchisi esa obyekt ({"0":"a","2":"c"}) bo'lib chiqadi.

Shuning uchun: filtrlagandan keyin deyarli har doim array_values() chaqiring. 18-bo'limda bu xato qanday API buzishini ko'ramiz.

Qo'shish va o'chirish #

PHP
$vazifalar = [];

// Oxiriga qo'shish
$vazifalar[] = "Hisobotni yozish";
$vazifalar[] = "Xatga javob berish";
array_push($vazifalar, "Uchrashuvga tayyorlanish");

// Boshiga qo'shish
array_unshift($vazifalar, "SHOSHILINCH: serverni tekshirish");

echo "Ro'yxat (" . count($vazifalar) . " ta):\n";
foreach ($vazifalar as $i => $v) {
    echo "  " . ($i + 1) . ". {$v}\n";
}

echo "\n";
$oxirgi = array_pop($vazifalar);
echo "array_pop olib tashladi:   {$oxirgi}\n";

$birinchi = array_shift($vazifalar);
echo "array_shift olib tashladi: {$birinchi}\n";

echo "\nQolgan: " . count($vazifalar) . " ta\n";
foreach ($vazifalar as $i => $v) {
    echo "  [{$i}] {$v}\n";
}
Natija
Ro'yxat (4 ta):
  1. SHOSHILINCH: serverni tekshirish
  2. Hisobotni yozish
  3. Xatga javob berish
  4. Uchrashuvga tayyorlanish

array_pop olib tashladi:   Uchrashuvga tayyorlanish
array_shift olib tashladi: SHOSHILINCH: serverni tekshirish

Qolgan: 2 ta
  [0] Hisobotni yozish
  [1] Xatga javob berish

Qidirish va tekshirish #

PHP
$ruxsatlar = ["o'qish", "yozish", "o'chirish"];
$narxlar = ["non" => 4000, "sut" => 12500, "shakar" => 9800];

printf("%-38s %s\n", "in_array('yozish'):", in_array("yozish", $ruxsatlar, true) ? "ha" : "yo'q");
printf("%-38s %s\n", "in_array('boshqarish'):", in_array("boshqarish", $ruxsatlar, true) ? "ha" : "yo'q");

echo "\n";
printf("%-38s %s\n", "array_key_exists('sut'):", array_key_exists("sut", $narxlar) ? "ha" : "yo'q");
printf("%-38s %s\n", "isset(\$narxlar['sut']):", isset($narxlar["sut"]) ? "ha" : "yo'q");

echo "\n";
$joy = array_search("o'chirish", $ruxsatlar, true);
echo "array_search o'rni: " . var_export($joy, true) . "\n";
$yoq = array_search("boshqarish", $ruxsatlar, true);
echo "Topilmasa qaytaradi: " . var_export($yoq, true) . "\n";

echo "\n";
echo "Kalitlar: " . implode(", ", array_keys($narxlar)) . "\n";
echo "Qiymatlar: " . implode(", ", array_values($narxlar)) . "\n";
echo "12500 ga mos kalit: " . array_search(12500, $narxlar, true) . "\n";
Natija
in_array('yozish'):                    ha
in_array('boshqarish'):                yo'q

array_key_exists('sut'):               ha
isset($narxlar['sut']):                ha

array_search o'rni: 2
Topilmasa qaytaradi: false

Kalitlar: non, sut, shakar
Qiymatlar: 4000, 12500, 9800
12500 ga mos kalit: sut
in_array ni uchinchi argumentsiz chaqirmang

in_array($nima, $massiv) standart holatda == bilan solishtiradi - ya'ni turlarni aylantiradi.

Bu qanday xavf tug'diradi:

PHP
$ruxsat_berilgan = [1, 2, 3];
in_array("1abc", $ruxsat_berilgan);         // PHP 7 da TRUE edi
in_array(true, $ruxsat_berilgan);           // TRUE - har qanday son bilan

Uchinchi argument true - bu qat'iy solishtirish (===) degani:

PHP
in_array($nima, $massiv, true);      // har doim shunday
array_search($nima, $massiv, true);  // bu ham
array_keys($massiv, $qiymat, true);  // bu ham

Xuddi shu holat array_search uchun ham amal qiladi.

isset va array_key_exists farqi ham muhim:

Kalit yo'qKalit bor, qiymati null
isset()falsefalse
array_key_exists()falsetrue

Ya'ni isset null qiymatni "yo'q" deb hisoblaydi. Agar null sizga mazmunli qiymat bo'lsa - array_key_exists ishlating.

Massiv funksiyalarini eslab qolish QAYTA ISHLAYDI (yangi massiv) array_map har bir elementni o'zgartiradi array_filter shartga mos kelganini qoldiradi array_reduce bitta qiymatga yig'adi array_slice bo'lagini oladi Asl massiv O'ZGARMAYDI JOYIDA O'ZGARTIRADI sort, rsort saralaydi, KALITNI YO'QOTADI asort, ksort kalitni saqlab saralaydi usort o'z qoidangiz bilan array_push, unset qo'shadi / o'chiradi Asl massiv O'ZGARADI Nom qoidasi: "a" bilan boshlansa - qiymat, "k" bo'lsa - kalit asort qiymat bo'yicha ksort kalit bo'yicha r = teskari (arsort) Filtrlagandan keyin array_values() ni unutmang array_filter kalitlarni saqlaydi: 0, 2, 5 kabi teshikli ketma-ketlik qoladi. JSON ga aylantirsangiz, massiv o'rniga {"0":..,"2":..} obyekti chiqadi.
Funksiya asl massivni o'zgartiradimi - buni har doim biling

map, filter, reduce #

PHP
$mahsulotlar = [
    ["nom" => "Klaviatura", "narx" => 350000,  "soni" => 3],
    ["nom" => "Sichqoncha", "narx" => 120000,  "soni" => 10],
    ["nom" => "Monitor",    "narx" => 2400000, "soni" => 2],
    ["nom" => "Quloqchin",  "narx" => 89000,   "soni" => 0],
];

// map - har biriga jami summani qo'shamiz
$hisoblangan = array_map(
    static fn(array $m): array => $m + ["jami" => $m["narx"] * $m["soni"]],
    $mahsulotlar
);

echo "Barcha mahsulotlar:\n";
foreach ($hisoblangan as $m) {
    printf("  %-12s %2d dona  %12s\n", $m["nom"], $m["soni"],
           number_format($m["jami"], 0, ",", " "));
}

// filter - faqat omborda borlarini qoldiramiz
$mavjud = array_values(array_filter(
    $hisoblangan,
    static fn(array $m): bool => $m["soni"] > 0
));

echo "\nOmborda bor: " . count($mavjud) . " ta\n";

// reduce - umumiy qiymatni hisoblaymiz
$umumiy = array_reduce(
    $mavjud,
    static fn(int $yigindi, array $m): int => $yigindi + $m["jami"],
    0
);

echo "Ombor qiymati: " . number_format($umumiy, 0, ",", " ") . " so'm\n";

// array_column - bitta ustunni ajratib olish
$nomlar = array_column($mavjud, "nom");
echo "Nomlar: " . implode(", ", $nomlar) . "\n";

// array_column kalit bilan - juda qulay
$narxJadvali = array_column($mahsulotlar, "narx", "nom");
echo "\nNarx jadvali:\n";
foreach ($narxJadvali as $nom => $narx) {
    printf("  %-12s %12s\n", $nom, number_format($narx, 0, ",", " "));
}
Natija
Barcha mahsulotlar:
  Klaviatura    3 dona     1 050 000
  Sichqoncha   10 dona     1 200 000
  Monitor       2 dona     4 800 000
  Quloqchin     0 dona             0

Omborda bor: 3 ta
Ombor qiymati: 7 050 000 so'm
Nomlar: Klaviatura, Sichqoncha, Monitor

Narx jadvali:
  Klaviatura        350 000
  Sichqoncha        120 000
  Monitor         2 400 000
  Quloqchin          89 000
array_column - eng kam baholanadigan funksiya

Ma'lumotlar bazasidan kelgan natija odatda shunday ko'rinadi:

PHP
[
    ["id" => 1, "nom" => "Ali",  "email" => "ali@..."],
    ["id" => 2, "nom" => "Vali", "email" => "vali@..."],
]

array_column uni bir chaqiruvda kerakli shaklga keltiradi:

ChaqiruvNatija
array_column($r, "nom")["Ali", "Vali"]
array_column($r, "nom", "id")[1 => "Ali", 2 => "Vali"]
array_column($r, null, "id")[1 => [...], 2 => [...]]

Uchinchi variant ayniqsa foydali: u butun qatorlarni id bo'yicha indekslaydi va keyin $foydalanuvchilar[5] deb to'g'ridan-to'g'ri murojaat qilish mumkin bo'ladi - tsikl bilan qidirish shart emas.

Obyektlar bilan ham ishlaydi: array_column($obyektlar, "nom") ochiq xossalarni oladi.

Saralash #

PHP
$baholar = ["Malika" => 88, "Husanboy" => 94, "Nodira" => 76, "Aziza" => 94];

$nusxa = $baholar;
arsort($nusxa);           // qiymat bo'yicha kamayish, kalit saqlanadi
echo "Ball bo'yicha (yuqoridan):\n";
foreach ($nusxa as $ism => $ball) {
    printf("  %-10s %d\n", $ism, $ball);
}

$nusxa = $baholar;
ksort($nusxa);            // kalit bo'yicha
echo "\nAlifbo bo'yicha:\n";
echo "  " . implode(", ", array_keys($nusxa)) . "\n";

echo "\n";
// usort - o'z qoidangiz bilan, ko'p mezonli saralash
$talabalar = [
    ["ism" => "Malika",   "ball" => 88, "yosh" => 20],
    ["ism" => "Husanboy", "ball" => 94, "yosh" => 25],
    ["ism" => "Aziza",    "ball" => 94, "yosh" => 22],
    ["ism" => "Nodira",   "ball" => 76, "yosh" => 21],
];

usort($talabalar, static function (array $a, array $b): int {
    // Avval ball bo'yicha kamayish tartibida
    $farq = $b["ball"] <=> $a["ball"];
    // Ball teng bo'lsa - yosh bo'yicha o'sish tartibida
    return $farq !== 0 ? $farq : ($a["yosh"] <=> $b["yosh"]);
});

echo "Ko'p mezonli saralash:\n";
foreach ($talabalar as $t) {
    printf("  %-10s ball %d, yosh %d\n", $t["ism"], $t["ball"], $t["yosh"]);
}
Natija
Ball bo'yicha (yuqoridan):
  Husanboy   94
  Aziza      94
  Malika     88
  Nodira     76

Alifbo bo'yicha:
  Aziza, Husanboy, Malika, Nodira

Ko'p mezonli saralash:
  Aziza      ball 94, yosh 22
  Husanboy   ball 94, yosh 25
  Malika     ball 88, yosh 20
  Nodira     ball 76, yosh 21
<=> - kosmik kema operatori

$a <=> $b uch qiymatdan birini qaytaradi:

HolatNatija
$a < $b-1
$a === $b0
$a > $b1

Bu aynan usort kutgan narsa, shuning uchun solishtiruvchi funksiyalar juda qisqa yoziladi:

PHP
usort($m, fn($a, $b) => $a["narx"] <=> $b["narx"]);

Tartibni teskari qilish uchun argumentlarni almashtiring: $b["narx"] <=> $a["narx"].

Ko'p mezonli saralashning qisqa shakli ham bor - massivlarni solishtirish:

PHP
usort($t, fn($a, $b) =>
    [$b["ball"], $a["yosh"]] <=> [$a["ball"], $b["yosh"]]
);

PHP massivlarni element-element solishtiradi, shuning uchun bu ikki mezonni birdan hal qiladi.

Ko'p o'lchovli massivlar #

PHP
$guruhlar = [
    "KI-21" => [
        ["ism" => "Malika", "ball" => 88],
        ["ism" => "Nodira", "ball" => 76],
    ],
    "KI-22" => [
        ["ism" => "Husanboy", "ball" => 94],
        ["ism" => "Aziza",    "ball" => 91],
        ["ism" => "Kamola",   "ball" => 83],
    ],
];

foreach ($guruhlar as $guruh => $talabalar) {
    $ballar = array_column($talabalar, "ball");
    $ortacha = array_sum($ballar) / count($ballar);

    printf("%s (%d talaba, o'rtacha %.2f)\n", $guruh, count($talabalar), $ortacha);
    foreach ($talabalar as $t) {
        printf("    %-10s %d\n", $t["ism"], $t["ball"]);
    }
}

echo "\n";
// Barcha talabalarni bitta ro'yxatga yig'ish
$hammasi = array_merge(...array_values($guruhlar));
echo "Jami talabalar: " . count($hammasi) . "\n";

$engYaxshi = array_reduce(
    $hammasi,
    static fn(?array $eng, array $t): array =>
        $eng === null || $t["ball"] > $eng["ball"] ? $t : $eng
);
echo "Eng yuqori ball: {$engYaxshi['ism']} ({$engYaxshi['ball']})\n";
Natija
KI-21 (2 talaba, o'rtacha 82.00)
    Malika     88
    Nodira     76
KI-22 (3 talaba, o'rtacha 89.33)
    Husanboy   94
    Aziza      91
    Kamola     83

Jami talabalar: 5
Eng yuqori ball: Husanboy (94)
Amaliy topshiriq
  1. Indeksli va assotsiativ massiv yarating, ikkalasini foreach bilan chiqaring.
  2. ["a","b","c"] dan unset($m[1]) qiling va kalitlarni ko'ring.
  3. array_values() bilan kalitlarni qayta raqamlang.
  4. in_array ni uchinchi argumentsiz va true bilan solishtiring.
  5. isset va array_key_exists ni null qiymatli kalitda sinang.
  6. array_map bilan har bir narxga soliq qo'shing.
  7. array_filter dan keyin JSON ga aylantiring - massivmi yoki obyekt?
  8. array_column bilan id bo'yicha indekslangan jadval yasang.
  9. usort va <=> bilan ikki mezon bo'yicha saralang.
  10. array_merge(...) bilan ko'p o'lchovli massivni yassilang.

Xulosa #

  • PHP massivi - tartiblangan xarita; indeksli massiv shunchaki butun sonli kalitlarga ega.
  • unset() kalitlarni qayta raqamlamaydi - array_values() chaqiring.
  • Filtrlangan massivni JSON ga aylantirsangiz, u obyekt bo'lib chiqishi mumkin.
  • in_array, array_search, array_keys ga har doim uchinchi argument true bering.
  • isset() null qiymatni "yo'q" deb hisoblaydi; array_key_exists() esa yo'q.
  • array_map, array_filter, array_reduce yangi massiv qaytaradi - asli o'zgarmaydi.
  • sort, usort, array_push esa massivni joyida o'zgartiradi.
  • Saralashda: a - qiymat bo'yicha, k - kalit bo'yicha, r - teskari.
  • array_column bazadan kelgan qatorlarni bir chaqiruvda qayta shakllantiradi.
  • <=> operatori usort uchun ideal; massivlarni solishtirib ko'p mezonni birdan hal qiladi.

Keyingi bo'limda shartlar, sikllar va match ifodasini ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.