Delo s polji

Ta stran je posvečena razredom Nette\Utils\Arrays, ArrayHash in ArrayList, ki se nanašajo na polja.

Namestitev:

composer require nette/utils

Arrays

Nette\Utils\Arrays je statični razred, ki vsebuje uporabne funkcije za delo s polji. Njegov ekvivalent za iteratorje je Nette\Utils\Iterables.

Naslednji primeri predpostavljajo ustvarjen alias:

use Nette\Utils\Arrays;

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

Funkcija fleksibilno pretvori polje $array v asociativno polje ali objekte glede na podano pot $path. Pot je lahko niz ali polje. Sestavljajo jo imena ključev vhodnega polja in operatorji, kot so ‘[]’, ‘->’, ‘=’, in ‘|’. V primeru neveljavne poti sproži Nette\InvalidArgumentException.

// pretvorba v asociativno polje po enostavnem ključu
$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]]
// dodelitev vrednosti iz enega ključa drugemu z uporabo operatorja =
$result = Arrays::associate($arr, 'name=age'); // ali ['name', '=', 'age']
// $result = ['John' => 11, 'Mary' => null, ...]
// ustvarjanje objekta z uporabo operatorja ->
$result = Arrays::associate($arr, '->name'); // ali ['->', 'name']
// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
// kombinacija ključev z uporabo operatorja |
$result = Arrays::associate($arr, 'name|age'); // ali ['name', '|', 'age']
// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
// dodajanje v polje z uporabo []
$result = Arrays::associate($arr, 'name[]'); // ali ['name', '[]']
// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]

contains (array $array, $value)bool

Preveri polje za prisotnost vrednosti. Uporablja strogo primerjavo (===).

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

every (array $array, callable $predicate)bool

Preveri, ali vsi elementi v polju prestanejo test, implementiran v $predicate s signaturo function ($value, $key, array $array): bool.

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

Glejte some().

filter (array $array, callable $predicate)array

Vrne novo polje, ki vsebuje vse pare ključ-vrednost, ki ustrezajo podanemu predikatu. Povratni klic ima signaturo 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

Vrne prvi element (ki ustreza predikatu, če je podan). Če tak element ne obstaja, vrne rezultat klica $else ali null. Parameter $predicate ima signaturo function ($value, int|string $key, array $array): bool.

Ne spremeni notranjega kazalca za razliko od reset(). Parametra $predicate in $else obstajata od različice 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

Glejte last().

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

Vrne ključ prvega elementa (ki ustreza predikatu, če je podan) ali null, če tak element ne obstaja. Predikat $predicate ima signaturo 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

Glejte lastKey().

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

Združi večnivojsko polje v ravno.

$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

Vrne element $array[$key]. Če ne obstaja, sproži bodisi izjemo Nette\InvalidArgumentException ali, če je podan tretji parameter $default, vrne tega.

// če $array['foo'] ne obstaja, sproži izjemo
$value = Arrays::get($array, 'foo');

// če $array['foo'] ne obstaja, vrne 'bar'
$value = Arrays::get($array, 'foo', 'bar');

Ključ $key je lahko tudi polje.

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

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

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

Pridobi referenco na določen element polja. Če element ne obstaja, bo ustvarjen z vrednostjo null.

$valueRef = & Arrays::getRef($array, 'foo');
// vrne referenco na $array['foo']

Tako kot funkcija get() zna delati z večdimenzionalnimi polji.

$value = & Arrays::getRef($array, ['color', 'favorite']);
// vrne referenco na $array['color']['favorite']

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

Vrne samo tiste elemente polja, katerih vrednost ustreza regularnemu izrazu $pattern. Če je $invert true, vrne nasprotno elemente, ki ne ustrezajo. Napaka pri prevajanju ali obdelavi izraza sproži izjemo Nette\RegexpException.

$filteredArray = Arrays::grep($array, '~^\d+$~');
// vrne samo elemente polja, sestavljene iz števk

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

Vstavi vsebino polja $inserted v polje $array takoj za element s ključem $key. Če je $key null (ali ga v polju ni), se vstavi na konec.

$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

Vstavi vsebino polja $inserted v polje $array pred element s ključem $key. Če je $key null (ali ga v polju ni), se vstavi na začetek.

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

invoke (iterable $callbacks, …$args)array

Kliče vse povratne klice in vrne polje rezultatov.

$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

Kliče metodo na vsakem objektu v polju in vrne polje rezultatov.

$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

Preveri, ali je polje indeksirano po naraščajočem zaporedju numeričnih ključev od nič, t.i. seznam (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

Vrne zadnji element (ki ustreza predikatu, če je podan). Če tak element ne obstaja, vrne rezultat klica $else ali null. Parameter $predicate ima signatururo function ($value, int|string $key, array $array): bool.

Ne spremeni notranjega kazalca za razliko od end(). Parametra $predicate in $else obstajata od različice 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

Glejte first().

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

Vrne ključ zadnjega elementa (ki ustreza predikatu, če je podan) ali null, če tak element ne obstaja. Predikat $predicate ima signaturo 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

Glejte firstKey().

map (array $array, callable $transformer)array

Kliče $transformer na vse elemente v polju in vrne polje vrnjenih vrednosti. Povratni klic ima signaturo function ($value, $key, array $array): bool.

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

mapWithKeys (array $array, callable $transformer)array

Ustvari novo polje s transformacijo vrednosti in ključev prvotnega polja. Funkcija $transformer ima signaturo function ($value, $key, array $array): ?array{$newKey, $newValue}. Če $transformer vrne null, je element preskočen. Za ohranjene elemente se prvi element vrnjenega polja uporabi kot nov ključ, drugi element pa kot nova vrednost.

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

Ta metoda je uporabna v situacijah, ko morate spremeniti strukturo polja (ključe in vrednosti hkrati) ali filtrirati elemente med transformacijo (z vračanjem null za neželene elemente).

mergeTree (array $array1, array $array2)array

Rekurzivno združi dve polji. Uporabno je na primer za združevanje drevesnih struktur. Pri združevanju sledi istim pravilom kot operator +, uporabljen na poljih, tj. prvemu polju dodaja pare ključ/vrednost iz drugega polja in v primeru kolizije ključev ohrani vrednost iz prvega polja.

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

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

Vrednosti iz drugega polja so vedno dodane na konec prvega. Malo zmedeno se lahko zdi izginotje vrednosti 10 iz drugega polja. Treba se je zavedati, da imata ta vrednost in prav tako vrednost 5 v prvem polju dodeljen isti numerični ključ 0, zato je v končnem polju samo element iz prvega polja.

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

Normalizira polje v asociativno polje. Numerične ključe nadomesti z njihovimi vrednostmi, nova vrednost bo $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

Vrne in odstrani vrednost elementa iz polja. Če ne obstaja, sproži izjemo ali vrne vrednost $default, če je podana.

$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');
// sproži Nette\InvalidArgumentException

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

Preimenuje ključ v polju. Vrne true, če je bil ključ najden v polju.

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

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

Vrne položaj danega ključa v polju. Položaj je oštevilčen od 0. V primeru, da ključ ni najden, funkcija vrne null.

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

some (array $array, callable $predicate)bool

Preveri, ali vsaj en element v polju prestane test, implementiran v $predicate s signaturo function ($value, $key, array $array): bool.

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

Glejte every().

toKey (mixed $key): string|int

Pretvori vrednost v ključ polja, ki je bodisi celo število (integer) ali niz.

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

toObject (iterable $array, object $object)object

Kopira elemente polja $array v objekt $object, ki ga nato vrne.

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

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

Vsak element v polju pretvori v niz in ga ovije s predpono $prefix in pripono $suffix.

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

ArrayHash

Objekt Nette\Utils\ArrayHash je potomec generičnega razreda stdClass in ga razširja z zmožnostjo obravnavanja kot polja, torej na primer dostopanja do članov prek oglatih oklepajev:

$hash = new Nette\Utils\ArrayHash;
$hash['foo'] = 123;
$hash->bar = 456; // hkrati deluje tudi objektni zapis
$hash->foo; // 123

Lahko uporabljate funkcijo count($hash) za ugotavljanje števila elementov.

Nad objektom je mogoče iterirati enako kot v primeru polja, tudi z referenco:

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

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

Obstoječe polje lahko pretvorimo v ArrayHash z metodo from():

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

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

Pretvorba je rekurzivna:

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

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

To lahko preprečite z drugim parametrom:

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

Transformacija nazaj v polje:

$array = (array) $hash;

ArrayList

Nette\Utils\ArrayList predstavlja linearno polje, kjer so indeksi samo cela števila naraščajoče od 0.

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

Obstoječe polje lahko pretvorimo v ArrayList z metodo from():

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

Lahko uporabljate funkcijo count($list) za ugotavljanje števila elementov.

Nad objektom je mogoče iterirati enako kot v primeru polja, tudi z referenco:

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

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

Dostop do ključev izven dovoljenih vrednosti sproži izjemo Nette\OutOfRangeException:

echo $list[-1]; // sproži Nette\OutOfRangeException
unset($list[30]); // sproži Nette\OutOfRangeException

Odstranitev ključa povzroči preštevilčenje elementov:

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

Nov element lahko dodate na začetek z metodo prepend():

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