Manipulation de tableaux
Cette page est dédiée aux classes Nette\Utils\Arrays, ArrayHash et ArrayList, qui concernent les tableaux.
Installation :
composer require nette/utils
Arrays
Nette\Utils\Arrays est une classe statique contenant des fonctions utiles pour travailler avec les tableaux. Son équivalent pour les itérateurs est Nette\Utils\Iterables.
Les exemples suivants supposent qu'un alias a été créé :
use Nette\Utils\Arrays;
associate (array $array, mixed $path): array|\stdClass
La fonction transforme de manière flexible le tableau $array
en un tableau associatif ou des objets selon le
chemin spécifié $path
. Le chemin peut être une chaîne ou un tableau. Il est constitué des noms des clés du
tableau d'entrée et d'opérateurs tels que ‘[]’, ‘->’, ‘=’, et ‘|’. Elle lève
Nette\InvalidArgumentException
si le chemin est invalide.
// conversion en tableau associatif selon une clé simple
$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]]
// assignation des valeurs d'une clé à une autre en utilisant l'opérateur =
$result = Arrays::associate($arr, 'name=age'); // ou ['name', '=', 'age']
// $result = ['John' => 11, 'Mary' => null, ...]
// création d'un objet en utilisant l'opérateur ->
$result = Arrays::associate($arr, '->name'); // ou ['->', 'name']
// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
// combinaison de clés à l'aide de l'opérateur |
$result = Arrays::associate($arr, 'name|age'); // ou ['name', '|', 'age']
// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
// ajout à un tableau en utilisant []
$result = Arrays::associate($arr, 'name[]'); // ou ['name', '[]']
// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
contains (array $array, $value): bool
Teste la présence d'une valeur dans le tableau. Utilise une comparaison stricte (===
).
Arrays::contains([1, 2, 3], 1); // true
Arrays::contains(['1', false], 1); // false
every (array $array, callable $predicate): bool
Teste si tous les éléments du tableau passent le test implémenté dans $predicate
avec la signature
function ($value, $key, array $array): bool
.
$array = [1, 30, 39, 29, 10, 13];
$isBelowThreshold = fn($value) => $value < 40;
$res = Arrays::every($array, $isBelowThreshold); // true
Voir some().
filter (array $array, callable $predicate): array
Retourne un nouveau tableau contenant toutes les paires clé-valeur correspondant au prédicat spécifié. Le callback a la
signature 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
Retourne le premier élément (correspondant au prédicat, s'il est spécifié). Si un tel élément n'existe pas, retourne le
résultat de l'appel de $else
ou null. Le paramètre $predicate
a la signature
function ($value, int|string $key, array $array): bool
.
Ne modifie pas le pointeur interne contrairement à reset()
. Les paramètres $predicate
et
$else
existent depuis la version 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
Voir last().
firstKey (array $array, ?callable $predicate=null): int|string|null
Retourne la clé du premier élément (correspondant au prédicat, s'il est spécifié) ou null si un tel élément n'existe
pas. Le prédicat $predicate
a la signature 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
Voir lastKey().
flatten (array $array, bool $preserveKeys=false): array
Aplatit un tableau multidimensionnel en un tableau 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
Retourne l'élément $array[$key]
. S'il n'existe pas, lève soit une exception
Nette\InvalidArgumentException
, soit, si le troisième paramètre $default
est spécifié, retourne
celui-ci.
// si $array['foo'] n'existe pas, lève une exception
$value = Arrays::get($array, 'foo');
// si $array['foo'] n'existe pas, retourne 'bar'
$value = Arrays::get($array, 'foo', 'bar');
La clé $key
peut aussi être un tableau.
$array = ['color' => ['favorite' => 'red'], 5];
$value = Arrays::get($array, ['color', 'favorite']);
// retourne 'red'
getRef (array &$array, string|int|array $key): mixed
Obtient une référence à l'élément spécifié du tableau. Si l'élément n'existe pas, il sera créé avec la valeur null.
$valueRef = & Arrays::getRef($array, 'foo');
// retourne une référence à $array['foo']
Comme la fonction get(), elle peut travailler avec des tableaux multidimensionnels.
$value = & Arrays::getRef($array, ['color', 'favorite']);
// retourne une référence à $array['color']['favorite']
grep (array $array, string $pattern, bool $invert=false): array
Retourne uniquement les éléments du tableau dont la valeur correspond à l'expression régulière $pattern
. Si
$invert
est true
, retourne au contraire les éléments qui ne correspondent pas. Une erreur lors de la
compilation ou du traitement de l'expression lève une exception Nette\RegexpException
.
$filteredArray = Arrays::grep($array, '~^\d+$~');
// retourne uniquement les éléments du tableau constitués de chiffres
insertAfter (array &$array, string|int|null $key, array $inserted): void
Insère le contenu du tableau $inserted
dans le tableau $array
juste après l'élément avec la clé
$key
. Si $key
est null
(ou n'est pas dans le tableau), il est inséré à la fin.
$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
Insère le contenu du tableau $inserted
dans le tableau $array
avant l'élément avec la clé
$key
. Si $key
est null
(ou n'est pas dans le tableau), il est inséré au début.
$array = ['first' => 10, 'second' => 20];
Arrays::insertBefore($array, 'first', ['hello' => 'world']);
// $array = ['hello' => 'world', 'first' => 10, 'second' => 20];
invoke (iterable $callbacks, …$args): array
Appelle tous les callbacks et retourne un tableau des résultats.
$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
Appelle la méthode sur chaque objet du tableau et retourne un tableau des résultats.
$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
Vérifie si le tableau est indexé selon une séquence ascendante de clés numériques à partir de zéro, alias une liste.
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
Retourne le dernier élément (correspondant au prédicat, s'il est spécifié). Si un tel élément n'existe pas, retourne le
résultat de l'appel de $else
ou null. Le paramètre $predicate
a la signature
function ($value, int|string $key, array $array): bool
.
Ne modifie pas le pointeur interne contrairement à end()
. Les paramètres $predicate
et
$else
existent depuis la version 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
Voir first().
lastKey (array $array, ?callable $predicate=null): int|string|null
Retourne la clé du dernier élément (correspondant au prédicat, s'il est spécifié) ou null si un tel élément n'existe
pas. Le prédicat $predicate
a la signature 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
Voir firstKey().
map (array $array, callable $transformer): array
Appelle $transformer
sur tous les éléments du tableau et retourne un tableau des valeurs retournées. Le
callback a la signature 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
Crée un nouveau tableau en transformant les valeurs et les clés du tableau original. La fonction $transformer
a
la signature function ($value, $key, array $array): ?array{$newKey, $newValue}
. Si $transformer
retourne
null
, l'élément est ignoré. Pour les éléments conservés, le premier élément du tableau retourné est utilisé
comme nouvelle clé et le second élément comme nouvelle valeur.
$array = ['a' => 1, 'b' => 2, 'c' => 3];
$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
// [4 => 'B']
Cette méthode est utile dans les situations où vous devez modifier la structure du tableau (clés et valeurs simultanément) ou filtrer des éléments lors de la transformation (en retournant null pour les éléments indésirables).
mergeTree (array $array1, array $array2): array
Fusionne récursivement deux tableaux. Utile par exemple pour fusionner des structures arborescentes. Lors de la fusion, elle
suit les mêmes règles que l'opérateur +
appliqué aux tableaux, c'est-à-dire qu'elle ajoute les paires
clé/valeur du second tableau au premier et, en cas de collision de clés, conserve la valeur du premier tableau.
$array1 = ['color' => ['favorite' => 'red'], 5];
$array2 = [10, 'color' => ['favorite' => 'green', 'blue']];
$array = Arrays::mergeTree($array1, $array2);
// $array = ['color' => ['favorite' => 'red', 'blue'], 5];
Les valeurs du second tableau sont toujours ajoutées à la fin du premier. La disparition de la valeur 10
du
second tableau peut sembler un peu déroutante. Il faut réaliser que cette valeur, ainsi que la valeur 5
dans le
premier tableau, ont la même clé numérique 0
assignée, c'est pourquoi dans le tableau résultant, il n'y a que
l'élément du premier tableau.
normalize (array $array, ?string $filling=null): array
Normalise le tableau en un tableau associatif. Remplace les clés numériques par leurs valeurs, la nouvelle valeur sera
$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
Retourne et supprime la valeur de l'élément du tableau. S'il n'existe pas, lève une exception, ou retourne la valeur
$default
si elle est spécifiée.
$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
Renomme une clé dans le tableau. Retourne true
si la clé a été trouvée dans le tableau.
$array = ['first' => 10, 'second' => 20];
Arrays::renameKey($array, 'first', 'renamed');
// $array = ['renamed' => 10, 'second' => 20];
getKeyOffset (array $array, string|int $key): ?int
Retourne la position de la clé donnée dans le tableau. La position est numérotée à partir de 0. Si la clé n'est pas
trouvée, la fonction retourne null
.
$array = ['first' => 10, 'second' => 20];
$position = Arrays::getKeyOffset($array, 'first'); // retourne 0
$position = Arrays::getKeyOffset($array, 'second'); // retourne 1
$position = Arrays::getKeyOffset($array, 'not-exists'); // retourne null
some (array $array, callable $predicate): bool
Teste si au moins un élément du tableau passe le test implémenté dans $predicate
avec la signature
function ($value, $key, array $array): bool
.
$array = [1, 2, 3, 4];
$isEven = fn($value) => $value % 2 === 0;
$res = Arrays::some($array, $isEven); // true
Voir every().
toKey (mixed $key): string|int
Convertit une valeur en clé de tableau, qui est soit un entier, soit une chaîne de caractères.
Arrays::toKey('1'); // 1
Arrays::toKey('01'); // '01'
toObject (iterable $array, object $object): object
Copie les éléments du tableau $array
dans l'objet $object
, qu'il retourne ensuite.
$obj = new stdClass;
$array = ['foo' => 1, 'bar' => 2];
Arrays::toObject($array, $obj); // définit $obj->foo = 1; $obj->bar = 2;
wrap (array $array, string
$prefix=''
, string $suffix=''
): array
Convertit chaque élément du tableau en chaîne de caractères et l'entoure du préfixe $prefix
et du suffixe
$suffix
.
$array = Arrays::wrap(['a' => 'red', 'b' => 'green'], '<<', '>>');
// $array = ['a' => '<<red>>', 'b' => '<<green>>'];
ArrayHash
L'objet Nette\Utils\ArrayHash est un descendant de la classe générique stdClass et l'étend avec la capacité de le traiter comme un tableau, c'est-à-dire par exemple d'accéder aux membres via des crochets :
$hash = new Nette\Utils\ArrayHash;
$hash['foo'] = 123;
$hash->bar = 456; // la notation objet fonctionne également
$hash->foo; // 123
Il est possible d'utiliser la fonction count($hash)
pour obtenir le nombre d'éléments.
On peut itérer sur l'objet de la même manière que sur un tableau, y compris avec une référence :
foreach ($hash as $key => $value) {
// ...
}
foreach ($hash as $key => &$value) {
$value = 'new value';
}
Un tableau existant peut être transformé en ArrayHash
avec la méthode from()
:
$array = ['foo' => 123, 'bar' => 456];
$hash = Nette\Utils\ArrayHash::from($array);
$hash->foo; // 123
$hash->bar; // 456
La conversion est récursive :
$array = ['foo' => 123, 'inner' => ['a' => 'b']];
$hash = Nette\Utils\ArrayHash::from($array);
$hash->inner; // objet ArrayHash
$hash->inner->a; // 'b'
$hash['inner']['a']; // 'b'
Cela peut être évité avec le second paramètre :
$hash = Nette\Utils\ArrayHash::from($array, false);
$hash->inner; // tableau
Transformation inverse en tableau :
$array = (array) $hash;
ArrayList
Nette\Utils\ArrayList représente un tableau linéaire, où les indices sont uniquement des entiers croissants à partir de 0.
$list = new Nette\Utils\ArrayList;
$list[] = 'a';
$list[] = 'b';
$list[] = 'c';
// ArrayList(0 => 'a', 1 => 'b', 2 => 'c')
count($list); // 3
Un tableau existant peut être transformé en ArrayList
avec la méthode from()
:
$array = ['foo', 'bar'];
$list = Nette\Utils\ArrayList::from($array);
Il est possible d'utiliser la fonction count($list)
pour obtenir le nombre d'éléments.
On peut itérer sur l'objet de la même manière que sur un tableau, y compris avec une référence :
foreach ($list as $key => $value) {
// ...
}
foreach ($list as $key => &$value) {
$value = 'new value';
}
L'accès à des clés en dehors des valeurs autorisées lève une exception Nette\OutOfRangeException
:
echo $list[-1]; // lève Nette\OutOfRangeException
unset($list[30]); // lève Nette\OutOfRangeException
La suppression d'une clé provoque la renumérotation des éléments :
unset($list[1]);
// ArrayList(0 => 'a', 1 => 'c')
Un nouvel élément peut être ajouté au début avec la méthode prepend()
:
$list->prepend('d');
// ArrayList(0 => 'd', 1 => 'a', 2 => 'c')