Obținerea părților unei colecții
Uneori nu ai nevoie de un tablou întreg. Ai nevoie de o parte din el: un interval de elemente, primele sau ultimele câteva, bucăți de dimensiune egală sau o fereastră mobilă de vecini.
Unealta de bază pentru asta în PHP este array_slice. array_slice($words, $offset, $length) dă $length elemente, începând de la indicele $offset. Al doilea număr este un număr de elemente, nu un indice de final. Omite $length pentru a merge până la sfârșit. Un $offset negativ numără înapoi de la sfârșit, iar un $length negativ se oprește cu atâtea elemente înainte de sfârșit.
array_slice($s, $i, $n)—$nelemente, începând de la indicele$iarray_slice($s, 0, $n)— primele$nelementearray_slice($s, $i)— tot, de la indicele$ipână la sfârșitarray_slice($s, -$n)— ultimele$nelementearray_slice($s, 0, -$n)— tot, în afară de ultimele$nelemente
array_slice construiește întotdeauna un tablou nou și copiază în el elementele alese. Modificarea copiei nu modifică originalul, iar modificarea originalului nu modifică copia. În alte limbaje aceeași operație dă o vedere care împarte memoria cu originalul — în PHP asta nu se întâmplă niciodată.
Pentru bucăți de dimensiune egală PHP are o a doua funcție gata făcută, array_chunk. Pentru sarcinile pe care niciuna dintre aceste funcții nu le poate rezolva singură, lecția folosește o buclă for sau foreach și una sau două funcții ajutătoare mici.
Majoritatea exemplelor din această pagină folosesc aceleași date: cuvintele one two three four five six.
Felie (slice)
A tăia o felie înseamnă a lua elementele de la niște poziții alese.
Pentru o serie de poziții vecine, folosește array_slice: array_slice($words, 1, 3) dă elementele de la indicii 1, 2 și 3. Atenție: 3 este o lungime, nu un indice de final — pornește de la indicele 1 și ia 3 elemente.
array_slice nu poate sări peste elemente. Pentru a lua fiecare al doilea element, folosește o buclă for cu $i += 2. Pentru poziții pe care le enumeri tu, în propria ta ordine, array_map peste un tablou de indici alege elementul de la fiecare dintre ele.
O felie dintr-un interval
array_slice($words, 1, 3) pornește de la indicele 1 și ia 3 elemente: cuvintele de la indicii 1, 2 și 3. Rezultatul este un tablou nou, așa că o modificare a lui nu ar atinge $words. Programul afișează two, three, four.
Ieșire: script PHP
<?php
$words = ["one", "two", "three", "four", "five", "six"];
// decalaj 1, lungime 3: elementele de la indicii 1, 2 și 3
$part = array_slice($words, 1, 3);
echo implode(", ", $part), "\n";
O felie cu pas
Pentru a lua fiecare al doilea element, o buclă for cu $i += 2 trece prin indicii 0, 2 și 4 și strânge cuvintele. $part[] = ... adaugă un element la sfârșitul unui tablou.
Ieșire: script PHP
<?php
$words = ["one", "two", "three", "four", "five", "six"];
// ia fiecare al doilea element, de la indicele 0 până la indicele 4
$part = [];
for ($i = 0; $i <= 4; $i += 2) {
$part[] = $words[$i];
}
echo implode(", ", $part), "\n";
O felie după o listă de indici
Pozițiile 3, 5 și 0 sunt păstrate într-un tablou de numere. array_map caută $words[$i] pentru fiecare dintre ele, așa că rezultatul iese în ordinea indicilor: four, six, one.
Ieșire: script PHP
<?php
$words = ["one", "two", "three", "four", "five", "six"];
$indices = [3, 5, 0];
// alege elementul de la fiecare poziție, în această ordine
$part = array_map(fn($i) => $words[$i], $indices);
echo implode(", ", $part), "\n";
Take și drop
Take înseamnă a păstra un număr de elemente de la un capăt. Drop înseamnă a arunca un număr de elemente de la un capăt și a păstra restul.
În PHP ambele sunt apeluri la array_slice. array_slice($words, 0, 3) ia primele 3 elemente, iar array_slice($words, -3) ia ultimele 3 — un decalaj negativ numără înapoi de la sfârșit. array_slice($words, 1) aruncă primul element, iar array_slice($words, 0, -5) aruncă ultimele 5, pentru că o lungime negativă se oprește cu atâtea elemente înainte de sfârșit.
Există și variante condiționate: takeWhile, takeLastWhile, dropWhile și dropLastWhile. Acestea nu numără elemente. Ele merg de la un capăt și se opresc la primul element care nu trece o condiție. PHP nu are variante predefinite, așa că o funcție ajutătoare mică, cu o buclă foreach, face treaba — iar variantele Last pur și simplu inversează tabloul cu array_reverse, rulează aceeași funcție ajutătoare și inversează rezultatul la loc.
Ia primele sau ultimele n elemente
array_slice($words, 0, 3) păstrează primele 3 cuvinte. array_slice($words, -3) păstrează ultimele 3, pentru că un decalaj negativ numără înapoi de la sfârșit.
Ieșire: script PHP
<?php
$words = ["one", "two", "three", "four", "five", "six"];
$first3 = array_slice($words, 0, 3); // primele 3 elemente
$last3 = array_slice($words, -3); // ultimele 3 elemente
echo implode(", ", $first3), "\n";
echo implode(", ", $last3), "\n";
Aruncă primele sau ultimele n elemente
array_slice($words, 1) sare peste primul cuvânt și păstrează restul. array_slice($words, 0, -5) se oprește cu 5 elemente înainte de sfârșit, așa că rămâne doar one.
Ieșire: script PHP
<?php
$words = ["one", "two", "three", "four", "five", "six"];
$withoutFirst = array_slice($words, 1); // aruncă primul element
$withoutLast5 = array_slice($words, 0, -5); // aruncă ultimele 5 elemente
echo implode(", ", $withoutFirst), "\n";
echo implode(", ", $withoutLast5), "\n";
Ia atât timp cât o condiție este îndeplinită
takeWhile păstrează cuvintele de la început până întâlnește un cuvânt care începe cu f. str_starts_with() verifică începutul unui șir de caractere. takeLastWhile păstrează cuvintele de la sfârșit până întâlnește three: inversează tabloul cu array_reverse, rulează takeWhile și inversează rezultatul la loc.
Ieșire: script PHP
<?php
// takeWhile păstrează elementele de la început atât timp cât $keep spune da, apoi se oprește.
function takeWhile(array $items, callable $keep): array {
$result = [];
foreach ($items as $item) {
if (!$keep($item)) {
break;
}
$result[] = $item;
}
return $result;
}
// takeLastWhile face același lucru de la sfârșit: inversează, ia, inversează la loc.
function takeLastWhile(array $items, callable $keep): array {
return array_reverse(takeWhile(array_reverse($items), $keep));
}
$words = ["one", "two", "three", "four", "five", "six"];
$fromStart = takeWhile($words, fn($w) => !str_starts_with($w, "f"));
$fromEnd = takeLastWhile($words, fn($w) => $w !== "three");
echo implode(", ", $fromStart), "\n";
echo implode(", ", $fromEnd), "\n";
Aruncă atât timp cât o condiție este îndeplinită
dropWhile sare peste cuvintele de 3 litere de la început și păstrează tot de la three încolo. dropLastWhile sare peste cuvintele de la sfârșit atât timp cât acestea conțin litera i. str_contains() verifică dacă un șir de caractere conține o bucată de text.
Ieșire: script PHP
<?php
// dropWhile sare peste elementele de la început atât timp cât $skip spune da și păstrează restul.
function dropWhile(array $items, callable $skip): array {
$result = [];
$dropping = true;
foreach ($items as $item) {
if ($dropping && $skip($item)) {
continue;
}
$dropping = false;
$result[] = $item;
}
return $result;
}
// dropLastWhile face același lucru de la sfârșit: inversează, aruncă, inversează la loc.
function dropLastWhile(array $items, callable $skip): array {
return array_reverse(dropWhile(array_reverse($items), $skip));
}
$words = ["one", "two", "three", "four", "five", "six"];
$fromStart = dropWhile($words, fn($w) => strlen($w) === 3);
$fromEnd = dropLastWhile($words, fn($w) => str_contains($w, "i"));
echo implode(", ", $fromStart), "\n";
echo implode(", ", $fromEnd), "\n";
Bucăți (chunked)
A împărți în bucăți înseamnă a tăia un tablou în părți de aceeași dimensiune. Ultima bucată poate fi mai scurtă, când elementele nu se împart exact.
PHP are asta predefinit: array_chunk($numbers, 3) returnează un tablou de tablouri, iar ultima bucată, cea scurtă, iese corect de la sine. Fiindcă rezultatul este imbricat, json_encode îl afișează cu fiecare bucată în parantezele ei: [[0,1,2],[3,4,5],…].
Pentru a lucra imediat cu fiecare bucată, dă bucățile lui array_map: a transmite numele unei funcții predefinite ca șir de caractere, precum 'array_sum', funcționează la fel de bine ca o funcție-săgeată.
Împarte în bucăți de 3
Numerele de la 0 la 13 sunt tăiate în bucăți de 3 cu un singur apel la array_chunk. Ultima bucată are doar 2 elemente: [12,13].
Ieșire: script PHP
<?php
$numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
// array_chunk taie tabloul în bucăți de 3; ultima bucată este mai scurtă
$chunks = array_chunk($numbers, 3);
echo json_encode($chunks), "\n";
Adună fiecare bucată
Aceleași bucăți, dar fiecare este adunată cu funcția predefinită array_sum. Numele ei este transmis lui array_map ca șir de caractere. Se păstrează doar sumele: 3, 12, 21, 30, 25.
Ieșire: script PHP
<?php
$numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
// adună fiecare bucată de 3 cu array_sum; se păstrează doar sumele
$sums = array_map('array_sum', array_chunk($numbers, 3));
echo implode(", ", $sums), "\n";
Ferestre (windowed)
O fereastră este un grup de elemente vecine. Deplasarea ferestrei glisează grupul de-a lungul tabloului și strânge fiecare poziție. Spre deosebire de bucăți, ferestrele se suprapun.
PHP nu are un windowed predefinit. O buclă for care apelează array_slice($items, $i, $size) la fiecare poziție face asta, iar o funcție ajutătoare mică, windowed, o face reutilizabilă. Cu un $step, fereastra se deplasează cu mai multe poziții pe rând. Cu $partial setat pe true, o fereastră mai scurtă de la sfârșit este păstrată în loc să fie aruncată.
O fereastră de 2 care se deplasează cu 1 pas este același lucru cu împerecherea fiecărui element cu următorul. În PHP, array_map cu null în loc de funcție lipește două tablouri element cu element — dă-i tabloul fără ultimul element și tabloul fără primul, și obții perechile de vecini.
Ferestre de 3
Fereastra are 3 cuvinte și se deplasează cu 1 poziție pe rând. Bucla se oprește când o fereastră completă nu mai încape, așa că sunt 3 ferestre. Rezultatul este un tablou de tablouri, afișat cu json_encode.
Ieșire: script PHP
<?php
// windowed returnează fiecare grup de $size elemente, deplasându-se cu o poziție pe rând.
function windowed(array $items, int $size): array {
$result = [];
for ($i = 0; $i + $size <= count($items); $i++) {
$result[] = array_slice($items, $i, $size);
}
return $result;
}
$words = ["one", "two", "three", "four", "five"];
echo json_encode(windowed($words, 3)), "\n";
Ferestre cu pas și ferestre parțiale
Fereastra are 3 numere și se deplasează cu 2 poziții pe rând. Fiindcă $partial este true, ultima fereastră [9,10] este păstrată, chiar dacă este scurtă.
Ieșire: script PHP
<?php
// windowed returnează grupuri de $size elemente, deplasându-se cu $step poziții pe rând.
// Cu $partial = true, se păstrează și un grup mai scurt de la sfârșit.
function windowed(array $items, int $size, int $step = 1, bool $partial = false): array {
$result = [];
for ($i = 0; $i < count($items); $i += $step) {
$window = array_slice($items, $i, $size);
if (count($window) < $size && !$partial) {
break;
}
$result[] = $window;
}
return $result;
}
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
echo json_encode(windowed($numbers, 3, 2, true)), "\n";
Adună fiecare fereastră
Fiecare fereastră de 3 vecini este decupată cu array_slice și adunată cu array_sum. Se păstrează doar sumele: 6, 9, 12.
Ieșire: script PHP
<?php
$numbers = [1, 2, 3, 4, 5];
// adună fiecare fereastră de 3 vecini
$sums = [];
for ($i = 0; $i + 3 <= count($numbers); $i++) {
$sums[] = array_sum(array_slice($numbers, $i, 3));
}
echo implode(", ", $sums), "\n";
Împerechează fiecare element cu următorul
array_map(null, ...) împerechează fiecare cuvânt cu vecinul său: primului tablou-argument îi lipsește ultimul element, celui de-al doilea îi lipsește primul, așa că tablourile se aliniază ca vecini. A doua buclă compară aceiași vecini și reține dacă primul cuvânt este mai lung decât al doilea; json_encode afișează valorile booleene ca true și false.
Ieșire: script PHP
<?php
$letters = ["one", "two", "three", "four", "five"];
// array_map cu null lipește cele două tablouri element cu element:
// fiecare element, împerecheat cu cel de după el
$pairs = array_map(null, array_slice($letters, 0, -1), array_slice($letters, 1));
echo json_encode($pairs), "\n";
// aceeași parcurgere, dar se compară lungimile vecinilor
$longer = [];
for ($i = 0; $i + 1 < count($letters); $i++) {
$longer[] = strlen($letters[$i]) > strlen($letters[$i + 1]);
}
echo json_encode($longer), "\n";