Lucrul cu array-uri

Această pagină este dedicată claselor Nette\Utils\Arrays, ArrayHash și ArrayList, care se referă la array-uri.

Instalare:

composer require nette/utils

Arrays

Nette\Utils\Arrays este o clasă statică ce conține funcții utile pentru lucrul cu array-uri. Echivalentul său pentru iteratori este Nette\Utils\Iterables.

Următoarele exemple presupun crearea unui alias:

use Nette\Utils\Arrays;

associate (array $array, mixed $path): array|\stdClass

Funcția transformă flexibil array-ul $array într-un array asociativ sau obiecte conform căii specificate $path. Calea poate fi un șir sau un array. Este formată din numele cheilor array-ului de intrare și operatori precum ‘[]’, ‘->’, ‘=’, și ‘|’. Aruncă Nette\InvalidArgumentException în cazul în care calea este invalidă.

// conversie la array asociativ după o cheie simplă
$arr = [
    ['name' => 'John', 'age' => 11],
    ['name' => 'Mary', 'age' => null],
    // ...
];
$result = Arrays::associate($arr, 'name');
// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
// atribuirea valorilor de la o cheie la alta folosind operatorul =
$result = Arrays::associate($arr, 'name=age'); // sau ['name', '=', 'age']
// $result = ['John' => 11, 'Mary' => null, ...]
// crearea unui obiect folosind operatorul ->
$result = Arrays::associate($arr, '->name'); // sau ['->', 'name']
// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
// combinarea cheilor folosind operatorul |
$result = Arrays::associate($arr, 'name|age'); // sau ['name', '|', 'age']
// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
// adăugarea într-un array folosind []
$result = Arrays::associate($arr, 'name[]'); // sau ['name', '[]']
// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]

contains (array $array, $value)bool

Testează array-ul pentru prezența unei valori. Utilizează comparația strictă (===).

Arrays::contains([1, 2, 3], 1);    // true
Arrays::contains(['1', false], 1); // false

every (array $array, callable $predicate)bool

Testează dacă toate elementele din array trec testul implementat în $predicate cu semnătura function ($value, $key, array $array): bool.

$array = [1, 30, 39, 29, 10, 13];
$isBelowThreshold = fn($value) => $value < 40;
$res = Arrays::every($array, $isBelowThreshold); // true

Vezi some().

filter (array $array, callable $predicate)array

Returnează un nou array conținând toate perechile cheie-valoare care corespund predicatului specificat. Callback-ul are semnătura function ($value, int|string $key, array $array): bool.

Arrays::filter(
	['a' => 1, 'b' => 2, 'c' => 3],
	fn($v) => $v < 3,
);
// ['a' => 1, 'b' => 2]

first (array $array, ?callable $predicate=null, ?callable $else=null)mixed

Returnează primul element (care corespunde predicatului, dacă este specificat). Dacă un astfel de element nu există, returnează rezultatul apelării $else sau null. Parametrul $predicate are semnătura function ($value, int|string $key, array $array): bool.

Nu modifică pointerul intern, spre deosebire de reset(). Parametrii $predicate și $else există începând cu versiunea 4.0.4.

Arrays::first([1, 2, 3]);                   // 1
Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3
Arrays::first([]);                          // null
Arrays::first([], else: fn() => false);     // false

Vezi last().

firstKey (array $array, ?callable $predicate=null): int|string|null

Returnează cheia primului element (care corespunde predicatului, dacă este specificat) sau null dacă un astfel de element nu există. Predicatul $predicate are semnătura function ($value, int|string $key, array $array): bool.

Arrays::firstKey([1, 2, 3]);                   // 0
Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2
Arrays::firstKey(['a' => 1, 'b' => 2]);        // 'a'
Arrays::firstKey([]);                          // null

Vezi lastKey().

flatten (array $array, bool $preserveKeys=false)array

Unifică un array multi-nivel într-unul plat.

$array = Arrays::flatten([1, 2, [3, 4, [5, 6]]]);
// $array = [1, 2, 3, 4, 5, 6];

get (array $array, string|int|array $key, ?mixed $default=null)mixed

Returnează elementul $array[$key]. Dacă nu există, aruncă fie excepția Nette\InvalidArgumentException, fie, dacă este specificat al treilea parametru $default, îl returnează pe acesta.

// dacă $array['foo'] nu există, aruncă o excepție
$value = Arrays::get($array, 'foo');

// dacă $array['foo'] nu există, returnează 'bar'
$value = Arrays::get($array, 'foo', 'bar');

Cheia $key poate fi și un array.

$array = ['color' => ['favorite' => 'red'], 5];

$value = Arrays::get($array, ['color', 'favorite']);
// returnează 'red'

getRef (array &$array, string|int|array $key)mixed

Obține o referință la elementul specificat al array-ului. Dacă elementul nu există, va fi creat cu valoarea null.

$valueRef = & Arrays::getRef($array, 'foo');
// returnează o referință la $array['foo']

La fel ca funcția get(), poate lucra cu array-uri multidimensionale.

$value = & Arrays::getRef($array, ['color', 'favorite']);
// returnează o referință la $array['color']['favorite']

grep (array $array, string $pattern, bool $invert=false)array

Returnează doar acele elemente ale array-ului a căror valoare corespunde expresiei regulate $pattern. Dacă $invert este true, returnează invers, elementele care nu corespund. O eroare la compilarea sau procesarea expresiei aruncă excepția Nette\RegexpException.

$filteredArray = Arrays::grep($array, '~^\d+$~');
// returnează doar elementele array-ului formate din cifre

insertAfter (array &$array, string|int|null $key, array $inserted)void

Inserează conținutul array-ului $inserted în array-ul $array imediat după elementul cu cheia $key. Dacă $key este null (sau nu se află în array), se inserează la sfârșit.

$array = ['first' => 10, 'second' => 20];
Arrays::insertAfter($array, 'first', ['hello' => 'world']);
// $array = ['first' => 10, 'hello' => 'world', 'second' => 20];

insertBefore (array &$array, string|int|null $key, array $inserted)void

Inserează conținutul array-ului $inserted în array-ul $array înainte de elementul cu cheia $key. Dacă $key este null (sau nu se află în array), se inserează la început.

$array = ['first' => 10, 'second' => 20];
Arrays::insertBefore($array, 'first', ['hello' => 'world']);
// $array = ['hello' => 'world', 'first' => 10, 'second' => 20];

invoke (iterable $callbacks, …$args)array

Invocă toate callback-urile și returnează un array de rezultate.

$callbacks = [
	'+' => fn($a, $b) => $a + $b,
	'*' => fn($a, $b) => $a * $b,
];

$array = Arrays::invoke($callbacks, 5, 11);
// $array = ['+' => 16, '*' => 55];

invokeMethod (iterable $objects, string $method, …$args)array

Apelează o metodă pe fiecare obiect din array și returnează un array de rezultate.

$objects = ['a' => $obj1, 'b' => $obj2];

$array = Arrays::invokeMethod($objects, 'foo', 1, 2);
// $array = ['a' => $obj1->foo(1, 2), 'b' => $obj2->foo(1, 2)];

isList (array $array): bool

Verifică dacă array-ul este indexat conform unei serii ascendente de chei numerice de la zero, a.k.a list.

Arrays::isList(['a', 'b', 'c']); // true
Arrays::isList([4 => 1, 2, 3]); // false
Arrays::isList(['a' => 1, 'b' => 2]); // false

last (array $array, ?callable $predicate=null, ?callable $else=null)mixed

Returnează ultimul element (care corespunde predicatului, dacă este specificat). Dacă un astfel de element nu există, returnează rezultatul apelării $else sau null. Parametrul $predicate are semnătura function ($value, int|string $key, array $array): bool.

Nu modifică pointerul intern, spre deosebire de end(). Parametrii $predicate și $else există începând cu versiunea 4.0.4.

Arrays::last([1, 2, 3]);                   // 3
Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2
Arrays::last([]);                          // null
Arrays::last([], else: fn() => false);     // false

Vezi first().

lastKey (array $array, ?callable $predicate=null): int|string|null

Returnează cheia ultimului element (care corespunde predicatului, dacă este specificat) sau null dacă un astfel de element nu există. Predicatul $predicate are semnătura function ($value, int|string $key, array $array): bool.

Arrays::lastKey([1, 2, 3]);                    // 2
Arrays::lastKey([1, 2, 3], fn($v) => $v < 3);  // 1
Arrays::lastKey(['a' => 1, 'b' => 2]);         // 'b'
Arrays::lastKey([]);                           // null

Vezi firstKey().

map (array $array, callable $transformer)array

Apelează $transformer pe toate elementele din array și returnează un array de valori returnate. Callback-ul are semnătura function ($value, $key, array $array): mixed.

$array = ['foo', 'bar', 'baz'];
$res = Arrays::map($array, fn($value) => $value . $value);
// $res = ['foofoo', 'barbar', 'bazbaz']

mapWithKeys (array $array, callable $transformer)array

Creează un nou array prin transformarea valorilor și cheilor array-ului original. Funcția $transformer are semnătura function ($value, $key, array $array): ?array{$newKey, $newValue}. Dacă $transformer returnează null, elementul este omis. Pentru elementele păstrate, primul element al array-ului returnat este folosit ca nouă cheie și al doilea element ca nouă valoare.

$array = ['a' => 1, 'b' => 2];
$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
// [4 => 'B']

Această metodă este utilă în situații în care trebuie să schimbați structura unui array (cheile și valorile simultan) sau să filtrați elemente în timpul transformării (returnând null pentru elementele nedorite).

mergeTree (array $array1, array $array2)array

Combină recursiv două array-uri. Este util, de exemplu, pentru combinarea structurilor arborescente. La combinare, respectă aceleași reguli ca operatorul + aplicat pe array-uri, adică adaugă la primul array perechile cheie/valoare din al doilea array și, în caz de coliziune a cheilor, păstrează valoarea din primul array.

$array1 = ['color' => ['favorite' => 'red'], 5];
$array2 = [10, 'color' => ['favorite' => 'green', 'blue']];

$array = Arrays::mergeTree($array1, $array2);
// $array = ['color' => ['favorite' => 'red', 'blue'], 5];

Valorile din al doilea array sunt întotdeauna adăugate la sfârșitul primului. Dispariția valorii 10 din al doilea array poate părea puțin derutantă. Trebuie să realizăm că această valoare, la fel ca valoarea 5 din primul array, au atribuită aceeași cheie numerică 0, de aceea în array-ul rezultat este doar elementul din primul array.

normalize (array $array, ?string $filling=null)array

Normalizează array-ul la un array asociativ. Cheile numerice le înlocuiește cu valorile lor, noua valoare va fi $filling.

$array = Arrays::normalize([1 => 'first', 'a' => 'second']);
// $array = ['first' => null, 'a' => 'second'];
$array = Arrays::normalize([1 => 'first', 'a' => 'second'], 'foobar');
// $array = ['first' => 'foobar', 'a' => 'second'];

pick (array &$array, string|int $key, ?mixed $default=null)mixed

Returnează și elimină valoarea unui element din array. Dacă nu există, aruncă o excepție sau returnează valoarea $default, dacă este specificată.

$array = [1 => 'foo', null => 'bar'];
$a = Arrays::pick($array, null);
// $a = 'bar'
$b = Arrays::pick($array, 'not-exists', 'foobar');
// $b = 'foobar'
$c = Arrays::pick($array, 'not-exists');
// throws Nette\InvalidArgumentException

renameKey (array &$array, string|int $oldKey, string|int $newKey)bool

Redenumește o cheie în array. Returnează true dacă cheia a fost găsită în array.

$array = ['first' => 10, 'second' => 20];
Arrays::renameKey($array, 'first', 'renamed');
// $array = ['renamed' => 10, 'second' => 20];

getKeyOffset (array $array, string|int $key)?int

Returnează poziția cheii date în array. Poziția este numerotată de la 0. În cazul în care cheia nu este găsită, funcția returnează null.

$array = ['first' => 10, 'second' => 20];
$position = Arrays::getKeyOffset($array, 'first'); // returnează 0
$position = Arrays::getKeyOffset($array, 'second'); // returnează 1
$position = Arrays::getKeyOffset($array, 'not-exists'); // returnează null

some (array $array, callable $predicate)bool

Testează dacă cel puțin un element din array trece testul implementat în $predicate cu semnătura function ($value, $key, array $array): bool.

$array = [1, 2, 3, 4];
$isEven = fn($value) => $value % 2 === 0;
$res = Arrays::some($array, $isEven); // true

Vezi every().

toKey (mixed $key): string|int

Convertește o valoare într-o cheie de array, care este fie un integer, fie un șir.

Arrays::toKey('1');  // 1
Arrays::toKey('01'); // '01'

toObject (iterable $array, object $object)object

Copiază elementele array-ului $array în obiectul $object, pe care apoi îl returnează.

$obj = new stdClass;
$array = ['foo' => 1, 'bar' => 2];
Arrays::toObject($array, $obj); // setează $obj->foo = 1; $obj->bar = 2;

wrap (array $array, string $prefix='', string $suffix='')array

Fiecare element din array este convertit la șir și înconjurat cu prefixul $prefix și sufixul $suffix.

$array = Arrays::wrap(['a' => 'red', 'b' => 'green'], '<<', '>>');
// $array = ['a' => '<<red>>', 'b' => '<<green>>'];

ArrayHash

Obiectul Nette\Utils\ArrayHash este un descendent al clasei generice stdClass și o extinde cu capacitatea de a fi tratat ca un array, adică, de exemplu, accesarea membrilor prin paranteze drepte:

$hash = new Nette\Utils\ArrayHash;
$hash['foo'] = 123;
$hash->bar = 456; // funcționează și scrierea obiectuală
$hash->foo; // 123

Se poate utiliza funcția count($hash) pentru a afla numărul de elemente.

Peste obiect se poate itera la fel ca în cazul unui array, chiar și cu referință:

foreach ($hash as $key => $value) {
	// ...
}

foreach ($hash as $key => &$value) {
	$value = 'new value';
}

Un array existent poate fi transformat în ArrayHash prin metoda from():

$array = ['foo' => 123, 'bar' => 456];

$hash = Nette\Utils\ArrayHash::from($array);
$hash->foo; // 123
$hash->bar; // 456

Conversia este recursivă:

$array = ['foo' => 123, 'inner' => ['a' => 'b']];

$hash = Nette\Utils\ArrayHash::from($array);
$hash->inner; // obiect ArrayHash
$hash->inner->a; // 'b'
$hash['inner']['a']; // 'b'

Acest lucru poate fi prevenit cu al doilea parametru:

$hash = Nette\Utils\ArrayHash::from($array, false);
$hash->inner; // array

Transformarea înapoi în array:

$array = (array) $hash;

ArrayList

Nette\Utils\ArrayList reprezintă un array liniar, unde indicii sunt doar numere întregi crescătoare de la 0.

$list = new Nette\Utils\ArrayList;
$list[] = 'a';
$list[] = 'b';
$list[] = 'c';
// ArrayList(0 => 'a', 1 => 'b', 2 => 'c')
count($list); // 3

Un array existent poate fi transformat în ArrayList prin metoda from():

$array = ['foo', 'bar'];
$list = Nette\Utils\ArrayList::from($array);

Se poate utiliza funcția count($list) pentru a afla numărul de elemente.

Peste obiect se poate itera la fel ca în cazul unui array, chiar și cu referință:

foreach ($list as $key => $value) {
	// ...
}

foreach ($list as $key => &$value) {
	$value = 'new value';
}

Accesarea cheilor în afara valorilor permise aruncă excepția Nette\OutOfRangeException:

echo $list[-1]; // aruncă Nette\OutOfRangeException
unset($list[30]); // aruncă Nette\OutOfRangeException

Eliminarea unei chei cauzează renumerotarea elementelor:

unset($list[1]);
// ArrayList(0 => 'a', 1 => 'c')

Un element nou poate fi adăugat la început prin metoda prepend():

$list->prepend('d');
// ArrayList(0 => 'd', 1 => 'a', 2 => 'c')
versiune: 4.0