Al migrar a PHP 7.4 tengo que lidiar con un comportamiento diferente de algunas funciones de matriz como reset()
, current()
o con end()
respecto a ArrayObject. El siguiente ejemplo produce diferentes salidas:
<?php
$array = new \ArrayObject(["a", "b"]);
$item = end($array);
var_dump($item);
$array = ["a", "b"];
$item = end($array);
var_dump($item);
Con php 7.4 el resultado es:
bool(false)
string(1) "b"
En las versiones de PHP anteriores a 7.4, el resultado es el siguiente:
string(1) "b"
string(1) "b"
A end($array->getArrayCopy())
produce un aviso, pero podría ser una solución si se usa con una variable.
¿Hay alguna manera de emular el comportamiento de end()
con un ArrayObject
o ArrayIterator
? El ArrayObject podría ser muy grande, una iteración hasta el final podría no ser la mejor solución.
$item = $array[count($array)-1];
. No estoy seguro si esa es la solución más eficiente.Respuestas:
Desde PHP 7.4, los métodos de matriz no operan en una matriz interna, sino en
ArrayObject
sí misma. Resumí dos soluciones para eso.1. Obtener una matriz interna de objetos.
2. Crear Fachada de
ArrayObject
y agregar método personalizado end () a la clase actualizada.fuente
Puede convertir el objeto de matriz en una matriz para obtener las claves y luego usar end en las claves para obtener la última clave.
No es una solución bonita pero funciona.
Le sugiero que lo convierta en una función para que pueda llamarlo cuando sea necesario.
https://3v4l.org/HTGYn
Como una función:
fuente
array_keys()
solución con 3v4l.org/IaEMM/perf#output pero necesitaba un 20-30% más de memoria en comparación con unend()
simplegetArrayCopy()
3v4l.org/uYv59/perf#outputend
, puede crear una clase de contenedor que implementeArrayAccess
y tenga una función adicional que devuelva unaend
de la matriz privada interna que se operaría.array_keys
? ¿Por qué no lo lanzas directamente$arr = (array) $array
y luego$end = end($arr)
Un enfoque un poco más rápido sin convertir o usar un iterador sería no usar el constructor en primer lugar, y en su lugar usar un
append
método que creará una matriz en sí misma y que puede usarend
en esa matriz más tardecount($array) - 1
en caso de que agregue otra matriz más tarde, nos aseguramos de que$item
siempre sea el último elemento en la última matriz agregada.fuente
count()
podría ser útil en algunos casos, pero su ejemplo no funcionaría para algo como estonew \ArrayObject([123 => "a", 456 => "c"]);
append
lugar del constructor, usar append con tu ejemplo definitivamente funcionará.$array->append([123 => "a", 456 => "c"]
count
que no es para los elementos de su matriz, es para la matriz multidimensional queappend
creará. Para su matriz estamos utilizandoend
como de costumbre.append()
, podría usar unacount()
solución válida. Eso podría funcionar conappend('a')
yappend('b')
. La clave sería no permitir matrices asociativas, que es una posibilidad al extender ArrayObject.