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')
version: 4.0