Accediendo a una matriz asociativa por índice entero en PHP

92

Quiero establecer el valor de una matriz asociativa usando el índice de matriz del par clave / valor. Por ejemplo:

$my_arr = array( "bling" => "some bling", "bling2" => "lots O bling" );
$my_arr[1] = "not so much bling";  // Would change the value with key bling2.

¿Cómo se puede lograr esto sin usar la cadena de claves?

Marty
fuente

Respuestas:

188

Utilice array_keys .

$keys = array_keys($my_arr);
$my_arr[$keys[1]] = "not so much bling";

Espero que esto ayude.

Donovan
fuente
4
Como nota al margen, ¿por qué los desarrolladores de PHP crearían una forma tan poco intuitiva de acceder a una matriz?
Marty
3
@ Marty, esto tiene menos que ver con cómo lo implementaron los desarrolladores de PHP, sino más con su malentendido de cómo funcionan las matrices. Técnicamente, lo anterior todavía usa el nombre asociativo. No existe correlación entre las claves de índice numéricas y asociativas.
Gordon
2
Creas una matriz asociativa porque lo que estás buscando es más importante que su posición en la matriz. Creo que este es un buen punto. Supongamos que tiene una matriz con los nombres de los estudiantes como claves y las direcciones como valores. Puede comunicarse con la dirección de un estudiante por su nombre. La posición de la matriz es irrelevante. Y puede ordenar la matriz por name of the student.
Donovan
@Gordon técnicamente es cierto. Pero el programador proporciona un número, no una cadena. Creo que este es el significado de without using a key string.
Donovan
2
@Albert, está asignando este número a la cadena de clave correspondiente. array[1] === $array['foo']Aunque eso no significa eso . La matriz aún podría contener otro valor en $array[1]. Tenga en cuenta que no estoy diciendo que su solución sea incorrecta. Es la suposición del OP.
Gordon
27

No existe correlación entre las claves de índice numéricas y asociativas.

Cuando dice que desea establecer el valor de una matriz asociativa utilizando el índice de matriz de la clave / valor , entonces debe usar la clave dada, la configuración $array[1]no es lo mismo que la configuración $array['foo'].

Considere esta matriz

print_r( array('foo', 'foo' => 'bar', 'baz', 'some' => 'value') );

Esto le dará

Array
(
    [0] => foo
    [foo] => bar
    [1] => baz
    [some] => value
)

Foo es el segundo elemento de la matriz. Ese es el desplazamiento , pero no tiene nada que ver con el índice 1. Como puede ver, en esa matriz anterior, el índice 1 está asociado baz. Es incorrecto asumir que solo porque fooes la primera clave asociativa tiene algo que ver con la clave numérica real 1. Al igual someque no se correlaciona con 2.

Del mismo modo, para una matriz mixta como la que se muestra arriba, la solución array_keyssugerida en otra parte de este sitio no funcionará, porque

print_r( array_keys(array('foo', 'foo' => 'bar', 'baz', 'some' => 'value')) );

daré

Array
(
    [0] => 0
    [1] => foo
    [2] => 1
    [3] => some
)

Entonces, cuando lo haces $array[$keys[1]], realmente lo estás haciendo $array['foo']. Pero si quisiera acceder al segundo valor asociativo en esa matriz ( 'some'), no puede hacerlo $array[$keys[2]]porque eso evaluaría a $array[1]y eso es baz.

La compensación de un elemento no tiene ninguna relación con su clave o valor

print_r(
    array(
        100    => 'foo',
        'foo'  => 'bar',
        50     => 'baz',
        'some' => 'value'
    )
);

realmente significa

Array
( //key       value     offset/position
    [100]  => foo       // 0
    [foo]  => bar       // 1
    [50]   => baz       // 2
    [some] => value     // 3
)

lo que significa que el elemento en el desplazamiento 0 es foo aunque su clave es 100. Si desea extraer elementos de una matriz por desplazamiento, debe usar

$third = array_splice($array, 2, 1);
echo $third[0]; // baz

Esto crearía una matriz que contiene solo el elemento en la tercera posición.

O podrías usar un ArrayIterator. El ArrayIteratorimplementa una Seekableinterfaz que le permite buscar una posición / desplazamiento específico en la matriz y luego buscar eso:

$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value
Gordon
fuente
Minor nit: "si quisieras acceder al segundo valor asociativo en esa matriz ('algunos'), no puedes hacer $ array [$ keys [2]] porque eso evaluaría a $ array [1] y eso es baz" Técnicamente, eso se debe a que todas las claves, incluidas las numéricas, son claves asociativas , los 4 valores devueltos por array_keys. No existe una entidad como una "clave no asociativa". Si quería señalar que no puede devolver la clave de la segunda cadena (asumiendo que la matriz de claves solo contiene cadenas), entonces lo que dice es correcto. $stringKeys = array_filter(array_keys($array), "is_string");da claves de cadena.
ToolmakerSteve
17

Si bien array_keys()permite el acceso a la enésima tecla, array_valuesle dará el enésimo valor.

<?php
$array = [
   0     => 'Zero',
   '1'   => 'One',
   'Two' => 'Two',
];
echo array_values($array)[2];
?>

generará 'Dos'.

¿Hay alguna ventaja de uno sobre el otro? Bueno, el único menor que puedo ver es el número de accesos a la matriz.

Con array_keys()usted necesita 3.

  1. Obtenga las claves de la matriz de datos.
  2. Obtenga la enésima clave de la lista de claves.
  3. Obtenga el valor usando la enésima clave de la matriz de datos.

Con array_values(), solo necesitas 2.

  1. Obtenga los valores de la matriz de datos.
  2. Obtenga el enésimo valor de la lista de valores.

Pero, por otro lado, las claves son normalmente más pequeñas y los datos podrían estar enormemente anidados, por lo que, a fin de cuentas, array_keys()probablemente sea más seguro usar el .

Richard A Quadling
fuente
3

Si la matriz es grande, ambos array_keysy array_valuesserán un desperdicio ya que asignarán una nueva matriz del mismo tamaño que la original, solo para obtener la enésima clave (o valor).

array_sliceacepta un desplazamiento de entero y funciona en matrices asociativas. Puede usarlo para obtener (y configurar) la enésima clave en tiempo constante.

// This will at most allocate 2 temporary arrays of 1 element each
$key = array_keys(array_slice($array, $n, 1, true))[0];

$array[$key] = $value;
Jesse
fuente
2
¡Buena solución aquí!
Daan
1

Prueba esto. Funciona para ti.

$result= array_values($my_arr); // Array with indexes you need
Murali Krishna
fuente
1
Tenga cuidado al publicar en un hilo antiguo que ya tiene varias respuestas y una respuesta aceptada. Necesita explicar por qué su nueva respuesta es mejor que las existentes.
APC
0

Otra posibilidad es convertirlo en una matriz normal:

$ arraybuff = implosionar ("~~~", $ my_arr);
$ my_arr = explotar ("~~~", $ arraybuff);

Donde "~~~" es un delimitador que no aparecerá en sus datos.

Ahora puede acceder a la matriz utilizando índices numéricos iguales a las compensaciones.

Si aún necesita conservar su matriz asociativa, simplemente asígnela a una variable diferente.

phreditor
fuente
Dado que siempre y siempre debe considerar, este delimitador exacto puede ocurrir en sus datos, esta idea solo funciona en un 99,9999999%. Hay varias soluciones que funcionarán al 100%. Además, esto hace que el procesador trabaje mucho y desperdicie memoria para un simple acceso a la matriz.
user426486