Trabajo con arrays
Esta página se dedica a las clases Nette\Utils\Arrays, ArrayHash y ArrayList, que se refieren a los arrays.
Instalación:
composer require nette/utils
Arrays
Nette\Utils\Arrays es una clase estática que contiene funciones útiles para trabajar con arrays. Su equivalente para iteradores es Nette\Utils\Iterables.
Los siguientes ejemplos asumen que se ha creado un alias:
use Nette\Utils\Arrays;
associate (array $array, mixed $path): array|\stdClass
La función transforma flexiblemente el array $array
en un array asociativo u objetos según la ruta especificada
$path
. La ruta puede ser una cadena o un array. Está formada por los nombres de las claves del array de entrada y
operadores como ‘[]’, ‘->’, ‘=’, y ‘|’. Lanza Nette\InvalidArgumentException
en caso de que la
ruta sea inválida.
// conversión a array asociativo según 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]]
// asignación de valores de una clave a otra usando el operador =
$result = Arrays::associate($arr, 'name=age'); // o ['name', '=', 'age']
// $result = ['John' => 11, 'Mary' => null, ...]
// creación de un objeto usando el operador ->
$result = Arrays::associate($arr, '->name'); // o ['->', 'name']
// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]]
// combinación de claves mediante el operador |
$result = Arrays::associate($arr, 'name|age'); // o ['name', '|', 'age']
// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]]
// adición a un array usando []
$result = Arrays::associate($arr, 'name[]'); // o ['name', '[]']
// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]]
contains (array $array, $value): bool
Prueba si un array contiene un valor. Utiliza una comparación estricta (===
).
Arrays::contains([1, 2, 3], 1); // true
Arrays::contains(['1', false], 1); // false
every (array $array, callable $predicate): bool
Prueba si todos los elementos del array pasan la prueba implementada en $predicate
con la 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
Ver some().
filter (array $array, callable $predicate): array
Devuelve un nuevo array que contiene todos los pares clave-valor que coinciden con el predicado especificado. 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,
);
// ['a' => 1, 'b' => 2]
first (array $array, ?callable $predicate=null, ?callable $else=null): mixed
Devuelve el primer elemento (que coincide con el predicado, si se especifica). Si tal elemento no existe, devuelve el resultado
de llamar a $else
o null. El parámetro $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
Ver last().
firstKey (array $array, ?callable $predicate=null): int|string|null
Devuelve la clave del primer elemento (que coincide con el predicado, si se especifica) o null si tal elemento no existe. El
predicado $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
Ver lastKey().
flatten (array $array, bool $preserveKeys=false): array
Unifica un array multinivel en uno plano.
$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 una excepción Nette\InvalidArgumentException
,
o si se especifica el tercer parámetro $default
, lo 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
también puede ser un array.
$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 especificado del array. Si el elemento no existe, se creará con el valor null.
$valueRef = & Arrays::getRef($array, 'foo');
// devuelve una referencia a $array['foo']
Al igual que la función get(), puede trabajar con arrays multidimensionales.
$value = & Arrays::getRef($array, ['color', 'favorite']);
// devuelve una referencia a $array['color']['favorite']
grep (array $array, string $pattern, bool $invert=false): array
Devuelve solo aquellos elementos del array cuyo valor coincide con la expresión regular $pattern
. Si
$invert
es true
, devuelve por el contrario los elementos que no coinciden. Un error durante la
compilación o procesamiento de la expresión lanza una excepción 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 el array $array
justo después del elemento con la clave
$key
. Si $key
es null
(o no está 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 el array $array
antes del elemento con la clave
$key
. Si $key
es null
(o no está 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 y devuelve un array de 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
Llama al método en cada objeto del array y devuelve un array de 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 (array $array): bool
Verifica si el array está indexado según una serie ascendente de claves numéricas desde cero, alias 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 (que coincide con el predicado, si se especifica). Si tal elemento no existe, devuelve el
resultado de llamar a $else
o null. El parámetro $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
Ver first().
lastKey (array $array, ?callable $predicate=null): int|string|null
Devuelve la clave del último elemento (que coincide con el predicado, si se especifica) o null si tal elemento no existe. El
predicado $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
Ver firstKey().
map (array $array, callable $transformer): array
Llama a $transformer
en todos los elementos del array y devuelve un array de los valores devueltos. El callback
tiene la firma 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
Crea un nuevo array transformando los valores y claves del array original. La función $transformer
tiene la firma
function ($value, $key, array $array): ?array{$newKey, $newValue}
. Si $transformer
devuelve
null
, el elemento se omite. Para los elementos conservados, el primer elemento del array devuelto se usa como nueva
clave y el segundo elemento como nuevo valor.
$array = ['a' => 1, 'b' => 2, 'c' => 3];
$result = Arrays::mapWithKeys($array, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
// [4 => 'B']
Este método es útil en situaciones donde necesitas cambiar la estructura del array (claves y valores simultáneamente) o filtrar elementos durante la transformación (devolviendo null para elementos no deseados).
mergeTree (array $array1, array $array2): array
Fusiona recursivamente dos arrays. Es útil, por ejemplo, para fusionar estructuras de árbol. Durante la fusión, sigue las
mismas reglas que el operador +
aplicado a arrays, es decir, añade pares clave/valor del segundo array al primer
array y en caso de colisión de claves, conserva el valor del primer array.
$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 siempre se añaden al final del primero. Puede parecer un poco confuso la desaparición del valor
10
del segundo array. Hay que darse cuenta de que este valor, así como el valor 5
en el primer array,
tienen asignada la misma clave numérica 0
, por lo tanto, en el array resultante solo está el elemento del
primer array.
normalize (array $array, ?string $filling=null): array
Normaliza un array a un array asociativo. Reemplaza las claves numéricas con sus valores, el nuevo valor 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 el valor de un elemento del array. Si no existe, lanza una excepción, o devuelve el valor
$default
si se especifica.
$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
Renombra una clave en el array. Devuelve true
si la clave fue encontrada 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 de la clave dada en el array. La posición se numera desde 0. En caso de que la clave no sea encontrada,
la función devuelve null
.
$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
Prueba si al menos un elemento del array pasa la prueba implementada en $predicate
con la firma
function ($value, $key, array $array): bool
.
$array = [1, 2, 3, 4];
$isEven = fn($value) => $value % 2 === 0;
$res = Arrays::some($array, $isEven); // true
Ver every().
toKey (mixed $key): string|int
Convierte un valor a una clave de array, que es un entero o una cadena.
Arrays::toKey('1'); // 1
Arrays::toKey('01'); // '01'
toObject (iterable $array, object $object): object
Copia los elementos del array $array
al objeto $object
, que luego devuelve.
$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 cada elemento del array a una cadena y lo envuelve con el prefijo $prefix
y el sufijo
$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 extiende con la capacidad de tratarlo como un array, es decir, por ejemplo, acceder a los miembros a través de corchetes:
$hash = new Nette\Utils\ArrayHash;
$hash['foo'] = 123;
$hash->bar = 456; // al mismo tiempo funciona la notación de objeto
$hash->foo; // 123
Se puede usar la función count($hash)
para obtener el número de elementos.
Se puede iterar sobre el objeto igual que en el caso de un array, incluso con referencia:
foreach ($hash as $key => $value) {
// ...
}
foreach ($hash as $key => &$value) {
$value = 'new value';
}
Un array existente podemos transformarlo a ArrayHash
con el método from()
:
$array = ['foo' => 123, 'bar' => 456];
$hash = Nette\Utils\ArrayHash::from($array);
$hash->foo; // 123
$hash->bar; // 456
La conversión es recursiva:
$array = ['foo' => 123, 'inner' => ['a' => 'b']];
$hash = Nette\Utils\ArrayHash::from($array);
$hash->inner; // objeto ArrayHash
$hash->inner->a; // 'b'
$hash['inner']['a']; // 'b'
Esto se puede prevenir con el segundo parámetro:
$hash = Nette\Utils\ArrayHash::from($array, false);
$hash->inner; // array
Transformación de vuelta a array:
$array = (array) $hash;
ArrayList
Nette\Utils\ArrayList representa un array lineal, donde los índices son solo números enteros ascendentemente desde 0.
$list = new Nette\Utils\ArrayList;
$list[] = 'a';
$list[] = 'b';
$list[] = 'c';
// ArrayList(0 => 'a', 1 => 'b', 2 => 'c')
count($list); // 3
Un array existente podemos transformarlo a ArrayList
con el método from()
:
$array = ['foo', 'bar'];
$list = Nette\Utils\ArrayList::from($array);
Se puede usar la función count($list)
para obtener el número de elementos.
Se puede iterar sobre el objeto igual que en el caso de un array, incluso con referencia:
foreach ($list as $key => $value) {
// ...
}
foreach ($list as $key => &$value) {
$value = 'new value';
}
El acceso a claves fuera de los valores permitidos lanza una excepción Nette\OutOfRangeException
:
echo $list[-1]; // lanza Nette\OutOfRangeException
unset($list[30]); // lanza Nette\OutOfRangeException
La eliminación de una clave causa la renumeración de los elementos:
unset($list[1]);
// ArrayList(0 => 'a', 1 => 'c')
Se puede añadir un nuevo elemento al principio con el método prepend()
:
$list->prepend('d');
// ArrayList(0 => 'd', 1 => 'a', 2 => 'c')