Funciones para arrays
Esta página trata las clases Nette\Utils\Arrays, ArrayHash y ArrayList, relacionadas con los arrays.
Instalación:
composer require nette/utils
Arrays
Nette\Utils\Arrays es una clase estática con funciones útiles para trabajar con arrays. Su equivalente para los iteradores es Nette\Utils\Iterables.
Los ejemplos siguientes suponen que está definido el siguiente alias de clase:
use Nette\Utils\Arrays;
associate (array $array, string|array $path): array|\stdClass
Esta función transforma con flexibilidad el array $array en un array asociativo o en objetos, según la ruta
indicada $path. La ruta puede ser una cadena o un array. Se compone de los nombres de las claves del array de
entrada y de operadores como [], ->, = y |. Lanza
Nette\InvalidArgumentException si la ruta no es válida.
// convierte en un array asociativo usando una clave 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]]
// asigna los valores de una clave a otra con el operador =
$result = Arrays::associate($arr, 'name=age'); // o ['name', '=', 'age']
// $result = ['John' => 11, 'Mary' => null, ...]
// crea un objeto con el operador ->
$result = Arrays::associate($arr, '->name'); // o ['->', 'name']
// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
// agrupa en dos niveles con el operador |
$result = Arrays::associate($arr, 'name|age'); // o ['name', '|', 'age']
// $result: ['John' => [11 => ['name' => 'John', 'age' => 11]], 'Mary' => ['' => ['name' => 'Mary', 'age' => null]], ...]
// añade a un array con []
$result = Arrays::associate($arr, 'name[]'); // o ['name', '[]']
// $result: ['John' => [['name' => 'John', 'age' => 11]], 'Mary' => [['name' => 'Mary', 'age' => null]], ...]
contains (array $array, $value): bool
Comprueba si un array contiene un valor. Usa comparación estricta (===).
Arrays::contains([1, 2, 3], 1); // true
Arrays::contains(['1', false], 1); // false
every (array $array, callable $predicate): bool
Comprueba si todos los elementos del array pasan la prueba implementada por la función $predicate indicada, de
firma function ($value, $key, array $array): bool.
$array = [1, 30, 39, 29, 10, 13];
$isBelowThreshold = fn($value) => $value < 40;
$res = Arrays::every($array, $isBelowThreshold); // true
Vea some().
filter (array $array, callable $predicate): array
Devuelve un array nuevo con todas las parejas clave-valor que encajan con el $predicate dado. El callback tiene la
firma function ($value, int|string $key, array $array): bool.
Arrays::filter(
['a' => 1, 'b' => 2, 'c' => 3],
fn($v) => $v < 3,
);
// devuelve ['a' => 1, 'b' => 2]
first (array $array, ?callable $predicate=null, ?callable $else=null): mixed
Devuelve el primer elemento (el primero que encaje con el predicado, si se indica). Si no existe tal elemento, devuelve el
resultado de invocar $else o null. El $predicate tiene la firma
function ($value, int|string $key, array $array): bool.
No cambia el puntero interno, a diferencia de reset(). Los parámetros $predicate y
$else existen desde la versión 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
Vea last().
firstKey (array $array, ?callable $predicate=null): int|string|null
Devuelve la clave del primer elemento (el primero que encaje con el predicado, si se indica), o null si no existe tal
elemento. El $predicate tiene la firma 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
Vea lastKey().
flatten (array $array, bool $preserveKeys=false): array
Aplana un array de varios niveles en uno solo. Las claves se pueden conservar si $preserveKeys se pone
a true.
$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
Devuelve el elemento $array[$key]. Si no existe, lanza Nette\InvalidArgumentException, a menos que se
indique un valor predeterminado como tercer argumento, que es entonces el que se devuelve.
// si $array['foo'] no existe, lanza una excepción
$value = Arrays::get($array, 'foo');
// si $array['foo'] no existe, devuelve 'bar'
$value = Arrays::get($array, 'foo', 'bar');
La clave $key puede ser también un array que representa una ruta dentro de un array anidado.
$array = ['color' => ['favorite' => 'red'], 5];
$value = Arrays::get($array, ['color', 'favorite']);
// devuelve 'red'
getRef (array &$array, string|int|array $key): mixed
Obtiene una referencia al elemento indicado del array. Si el elemento no existe, se crea con el valor null.
$valueRef = & Arrays::getRef($array, 'foo');
// devuelve una referencia a $array['foo']
Funciona con arrays multidimensionales igual que get().
$value = & Arrays::getRef($array, ['color', 'favorite']);
// devuelve una referencia a $array['color']['favorite']
grep (array $array, string $pattern, bool $invert=false): array
Devuelve solo los elementos del array cuyo valor encaja con la expresión regular $pattern. Si
$invert es true, devuelve los elementos que no encajan. Un error de compilación o de ejecución
en la expresión lanza Nette\RegexpException.
$filteredArray = Arrays::grep($array, '~^\d+$~');
// devuelve solo los elementos del array formados por dígitos
insertAfter (array &$array, string|int|null $key, array $inserted): void
Inserta el contenido del array $inserted en $array inmediatamente después del elemento de clave
$key. Si $key es null (o no existe en el array), se inserta al final.
$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
Inserta el contenido del array $inserted en $array antes del elemento de clave $key. Si
$key es null (o no existe en el array), se inserta al principio.
$array = ['first' => 10, 'second' => 20];
Arrays::insertBefore($array, 'first', ['hello' => 'world']);
// $array = ['hello' => 'world', 'first' => 10, 'second' => 20];
invoke (iterable $callbacks, …$args): array
Invoca todos los callbacks del iterable y devuelve un array con los resultados.
$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
Invoca un método en cada objeto de un iterable y devuelve un array con los resultados.
$objects = ['a' => $obj1, 'b' => $obj2];
$array = Arrays::invokeMethod($objects, 'foo', 1, 2);
// $array = ['a' => $obj1->foo(1, 2), 'b' => $obj2->foo(1, 2)];
isList (mixed $value): bool
Comprueba si el array está indexado con claves numéricas ascendentes desde cero, es decir, si es una lista.
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
Devuelve el último elemento (el último que encaje con el predicado, si se indica). Si no existe tal elemento, devuelve el
resultado de invocar $else o null. El $predicate tiene la firma
function ($value, int|string $key, array $array): bool.
No cambia el puntero interno, a diferencia de end(). Los parámetros $predicate y $else
existen desde la versión 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
Vea first().
lastKey (array $array, ?callable $predicate=null): int|string|null
Devuelve la clave del último elemento (el último que encaje con el predicado, si se indica), o null si no existe tal
elemento. El $predicate tiene la firma 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
Vea firstKey().
map (array $array, callable $transformer): array
Llama a $transformer con todos los elementos del array y devuelve un array con los valores de retorno. El callback
tiene la firma 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
Crea un array nuevo transformando los valores y las claves del original. La función $transformer tiene la firma
function ($value, $key, array $array): ?array{$newKey, $newValue}. Si $transformer devuelve
null, el elemento se salta. En los elementos conservados, el primer elemento del array devuelto se usa como nueva
clave y el segundo, como nuevo valor.
$array = ['a' => 1, 'b' => 2];
$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
// [4 => 'B']
Este método resulta útil cuando necesita cambiar la estructura de un array (claves y valores a la vez) o filtrar elementos durante la transformación (devolviendo null para los no deseados).
mergeTree (array $array1, array $array2): array
Fusiona recursivamente dos arrays. Resulta útil, por ejemplo, para fusionar estructuras de árbol. Sigue las mismas reglas que
el operador + aplicado a arrays, es decir, añade al primero las parejas clave/valor del segundo y, en caso de
colisión de claves, conserva el valor del primero.
$array1 = ['color' => ['favorite' => 'red'], 5];
$array2 = [10, 'color' => ['favorite' => 'green', 'blue']];
$array = Arrays::mergeTree($array1, $array2);
// $array = ['color' => ['favorite' => 'red', 'blue'], 5];
Los valores del segundo array se añaden siempre al final del primero. Que el valor 10 del segundo array
desaparezca puede resultar algo confuso. Es importante darse cuenta de que a ese valor, igual que al valor 5 del
primer array, se le asigna la misma clave numérica 0. Por eso, el array resultante contiene para esa clave solo el
elemento del primer array.
normalize (array $array, ?string $filling=null): array
Normaliza un array en un array asociativo. Las claves numéricas se sustituyen por sus valores, y el nuevo valor pasa a ser
$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
Devuelve y elimina del array el valor del elemento de clave $key. Si el elemento no existe, lanza una excepción,
o devuelve $default si se ha indicado.
$array = [1 => 'foo', 'x' => 'bar'];
$a = Arrays::pick($array, 'x');
// $a = 'bar'
$b = Arrays::pick($array, 'not-exists', 'foobar');
// $b = 'foobar'
$c = Arrays::pick($array, 'not-exists');
// lanza Nette\InvalidArgumentException
renameKey (array &$array, string|int $oldKey, string|int $newKey): bool
Renombra una clave del array. Devuelve true si la clave se encontró en el array.
$array = ['first' => 10, 'second' => 20];
Arrays::renameKey($array, 'first', 'renamed');
// $array = ['renamed' => 10, 'second' => 20];
getKeyOffset (array $array, string|int $key): ?int
Devuelve la posición, indexada desde cero, de la clave dada del array. Devuelve null si no se encuentra
la clave.
$array = ['first' => 10, 'second' => 20];
$position = Arrays::getKeyOffset($array, 'first'); // devuelve 0
$position = Arrays::getKeyOffset($array, 'second'); // devuelve 1
$position = Arrays::getKeyOffset($array, 'not-exists'); // devuelve null
some (array $array, callable $predicate): bool
Comprueba si al menos un elemento del array pasa la prueba implementada por el callback $predicate indicado, de
firma function ($value, $key, array $array): bool.
$array = [1, 2, 3, 4];
$isEven = fn($value) => $value % 2 === 0;
$res = Arrays::some($array, $isEven); // true
Vea every().
toKey (mixed $value): string|int
Convierte un valor en clave de array, es decir, en un entero o una cadena. Los números en coma flotante se truncan, los
booleanos se convierten en 0 o 1, null pasa a ser una cadena vacía y los objetos lanzan una
excepción.
Arrays::toKey('1'); // 1
Arrays::toKey('01'); // '01'
toObject (iterable $array, object $object): object
Copia los elementos del iterable $array en el objeto $object y devuelve después el objeto.
$obj = new stdClass;
$array = ['foo' => 1, 'bar' => 2];
Arrays::toObject($array, $obj); // establece $obj->foo = 1; $obj->bar = 2;
wrap (array $array, string
$prefix='', string $suffix=''): array
Convierte a cadena cada elemento del array y lo envuelve con $prefix y $suffix.
$array = Arrays::wrap(['a' => 'red', 'b' => 'green'], '<<', '>>');
// $array = ['a' => '<<red>>', 'b' => '<<green>>'];
ArrayHash
El objeto Nette\Utils\ArrayHash es un descendiente
de la clase genérica stdClass y la amplía con la posibilidad de tratarlo como un array, por ejemplo accediendo a
sus miembros con corchetes:
$hash = new Nette\Utils\ArrayHash;
$hash['foo'] = 123;
$hash->bar = 456; // la notación de objeto también funciona
$hash->foo; // 123
Puede usar la función count($hash) para obtener el número de elementos.
Puede iterar sobre el objeto como si fuera un array, incluso por referencia:
foreach ($hash as $key => $value) {
// ...
}
foreach ($hash as $key => &$value) {
$value = 'new value';
}
Los arrays existentes se pueden transformar en un ArrayHash con el método estático from():
$array = ['foo' => 123, 'bar' => 456];
$hash = Nette\Utils\ArrayHash::from($array);
$hash->foo; // 123
$hash->bar; // 456
La conversión es recursiva: los eventuales subarrays se convierten también en objetos ArrayHash.
$array = ['foo' => 123, 'inner' => ['a' => 'b']];
$hash = Nette\Utils\ArrayHash::from($array);
$hash->inner; // object ArrayHash
$hash->inner->a; // 'b'
$hash['inner']['a']; // 'b'
Este comportamiento recursivo se puede desactivar con el segundo parámetro:
$hash = Nette\Utils\ArrayHash::from($array, false);
$hash->inner; // array
Transformación inversa a array mediante la conversión (array):
$array = (array) $hash;
ArrayList
Nette\Utils\ArrayList representa un array lineal cuyos índices son solo números enteros ascendentes desde 0.
$list = new Nette\Utils\ArrayList;
$list[] = 'a';
$list[] = 'b';
$list[] = 'c';
// ArrayList(0 => 'a', 1 => 'b', 2 => 'c')
count($list); // 3
Los arrays existentes se pueden transformar en ArrayList con el método estático from():
$array = ['foo', 'bar'];
$list = Nette\Utils\ArrayList::from($array);
Puede usar la función count($list) para obtener el número de elementos.
Puede iterar sobre el objeto como si fuera un array, incluso por referencia:
foreach ($list as $key => $value) {
// ...
}
foreach ($list as $key => &$value) {
$value = 'new value';
}
Acceder a claves fuera del rango permitido (de 0 a count-1) o intentar fijar claves no enteras lanza
Nette\OutOfRangeException:
echo $list[-1]; // lanza Nette\OutOfRangeException
unset($list[30]); // lanza Nette\OutOfRangeException
Eliminar una clave hace que los elementos se renumeren:
unset($list[1]);
// ArrayList(0 => 'a', 1 => 'c')
Puede añadir un elemento nuevo al principio con el método prepend():
$list->prepend('d');
// ArrayList(0 => 'd', 1 => 'a', 2 => 'c')