¿Obtener la primera clave en una (posiblemente) matriz asociativa?

757

¿Cuál es la mejor manera de determinar la primera clave en una matriz posiblemente asociativa? Lo primero que pensé fue simplemente predecir la matriz y luego romperla de inmediato, así:

foreach ($an_array as $key => $val) break;

Por lo tanto, tener $ key contiene la primera clave, pero esto parece ineficiente. ¿Alguien tiene una solución mejor?

Alex S
fuente
44
¿Por qué es ineficiente foreach?
Emilio Gort
2
En comparación con todas las respuestas, foreach sigue siendo el FIDDLE más rápido, PHP 5.3 , mi prueba localhost en PHP 5.5 muestra que la diferencia está ligeramente a favor de foreach.
Danijel
3
@Danijel, foreachestá semánticamente equivocado.
Pacerier
2
@AlexS, ya sea each($arr)['key']o each($arr)[0]funcionaría.
Pacerier
1
@Danijel Ya no más ... clave: 0.0107foreach:0.0217
SeanJA

Respuestas:

1338

Actualización 2019

A partir de PHP 7.3 , hay una nueva función incorporada llamada array_key_first()que recuperará la primera clave de la matriz dada sin restablecer el puntero interno. Consulte la documentación para más información.


Puedes usar resety key:

reset($array);
$first_key = key($array);

Es esencialmente lo mismo que su código inicial, pero con un poco menos de sobrecarga, y es más obvio lo que está sucediendo.

Solo recuerde llamar reset, o puede obtener cualquiera de las claves en la matriz. También puede usar en endlugar de resetobtener la última clave.

Si desea que la clave obtenga el primer valor, en resetrealidad lo devuelve:

$first_value = reset($array);

Sin embargo, hay un caso especial a tener en cuenta (así que primero verifique la longitud de la matriz):

$arr1 = array(false);
$arr2 = array();
var_dump(reset($arr1) === reset($arr2)); // bool(true)
Blixt
fuente
141
Como nota al margen, reset()también sucede que devuelve el primer elemento (valor, no clave) de cualquier matriz, que también puede ser útil.
devios1
55
Hay un comentario en los documentos que reset()dice Don't use reset () `para obtener el primer valor de una matriz asociativa. Funciona muy bien para matrices verdaderas, pero funciona inesperadamente en objetos Iterator. bugs.php.net/bug.php?id=38478 `¿Sigue siendo cierto? Estoy confundido
Dmitry Pashkevich
13
@DmitryPashkevich: No te preocupes por ese comentario. No están hablando de arrayobjetos, sino de objetos personalizados (que no son matrices reales). Supongo que confundieron la diferencia en las estructuras de datos, pero básicamente, resetdevuelve el valor de la primera "clave", que para los objetos estaría $propen el ejemplo dado en el informe "error", pero para una matriz la primera clave. Así que no se preocupe, siempre y cuando use matrices reales (creadas con array(…)), no tendrá ningún problema.
Blixt
2
Cabe mencionar que end () y reset () tienen un efecto secundario. Sin embargo, la mayoría del código en el mundo no se basa en que el puntero interno esté en ninguna parte, por lo que esto generalmente no es un problema.
donquixote
1
@ user3019105 Sólo hay un puntero interno por matriz, lo que significa que si cualquier código fuera de su función cambia (llamando next, reset, endo bucle a través de la matriz), no obtendrá el valor esperado cuando llame key. Entonces sí, siempre llame resetantes de usar keypara asegurarse de obtener lo que desea.
Blixt
80

array_keysdevuelve una matriz de claves. Toma la primera entrada. Alternativamente, puede llamar reseta la matriz y posteriormente key. El último enfoque es probablemente un poco más rápido (aunque no lo probé), pero tiene el efecto secundario de restablecer el puntero interno.

troelskn
fuente
52
Solo una nota (tardía) para futuros lectores de esto: el último enfoque no es solo "ligeramente" más rápido. Hay una gran diferencia entre iterar una matriz completa, almacenar cada clave en otra matriz recién creada y solicitar la primera clave de una matriz como una cadena.
Blixt
3
¿Por qué es ineficiente foreach como el op en la pregunta en comparación con todas estas respuestas?
Emilio Gort
55
@ EmilioGort Buena pregunta. No creo que haya ninguna diferencia en el rendimiento de foreach+ breaky reset+ en keyrealidad. Pero el primero parece bastante extraño, por lo que para cuestiones estilísticas, preferiría el segundo.
troelskn
@EmilioGort: Afaik, foreach () copia la matriz internamente. Entonces podemos suponer que es más lento. (Sería bueno si alguien pudiera confirmar eso)
donquixote
3
@donquixote No estoy seguro, pero suponiendo que sea una matriz regular (y no un objeto que implemente algún tipo de interfaz Iterator), estoy bastante seguro de foreachque no crea una copia interna, sino que simplemente itera un puntero , similar a usar el nivel más bajo next, currentetc.
troelskn
54

Curiosamente, el bucle foreach es en realidad la forma más eficiente de hacerlo.

Dado que el OP preguntó específicamente sobre la eficiencia, debe señalarse que todas las respuestas actuales son, de hecho, mucho menos eficientes que un foreach.

Hice un punto de referencia sobre esto con php 5.4, y el método de reinicio / puntero de tecla (respuesta aceptada) parece ser aproximadamente 7 veces más lento que un foreach. Otros enfoques que manipulan toda la matriz (array_keys, array_flip) son obviamente aún más lentos que eso y empeoran mucho cuando se trabaja con una matriz grande.

Foreach no es ineficiente en absoluto, ¡no dudes en usarlo!

Editar 2015-03-03:

Se han solicitado scripts de referencia, no tengo los originales, sino que hice algunas pruebas nuevas. Esta vez encontré el foreach solo el doble de rápido que reset / key. Utilicé una matriz de 100 teclas y ejecuté cada método un millón de veces para obtener una diferencia notable, aquí está el código del punto de referencia simple:

$array = [];
for($i=0; $i < 100; $i++)
    $array["key$i"] = $i;

for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    foreach ($array as $firstKey => $firstValue) {
        break;
    }
}
echo "foreach to get first key and value: " . (microtime(true) - $start) . " seconds <br />";

for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    $firstValue = reset($array);
    $firstKey = key($array);
}
echo "reset+key to get first key and value: " . (microtime(true) - $start) . " seconds <br />";

for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    reset($array);
    $firstKey = key($array);
}
echo "reset+key to get first key: " . (microtime(true) - $start) . " seconds <br />";


for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    $firstKey = array_keys($array)[0];
}
echo "array_keys to get first key: " . (microtime(true) - $start) . " seconds <br />";

En mi php 5.5 esto produce:

foreach to get first key and value: 0.15501809120178 seconds 
reset+key to get first key and value: 0.29375791549683 seconds 
reset+key to get first key: 0.26421809196472 seconds 
array_keys to get first key: 10.059751987457 seconds

reset + key http://3v4l.org/b4DrN/perf#tabs
foreach http://3v4l.org/gRoGD/perf#tabs

Webmut
fuente
3
¿Tienes los puntos de referencia en alguna parte? Como cómo lo probaste, etc. De todos modos, ¡gracias por ejecutarlos!
gripe
Me gustaría señalar el hecho de que se usa la misma matriz durante toda la prueba. Creo que este hecho influye significativamente en el enfoque foreach. Como @donquixote mencionó en el comentario a alguna respuesta anterior, foreach copia internamente la matriz. Me imagino que esta copia se reutiliza mientras se ejecuta el punto de referencia, ya que evitar la copia de matriz mejora el rendimiento solo dentro de esta prueba.
Jarda
2
@Jarda A partir de php7, foreachnunca copie la matriz a menos que la modifique directamente dentro del bucle foreach. En php5, la estructura de la matriz podría copiarse en algunos casos (cuando su recuento> 1) y en realidad tiene razón, podría ser una influencia significativa allí. Afortunadamente, no hay nada de qué preocuparse en php7, donde se resolvió este problema. Aquí hay una gran lectura sobre cómo funciona foreach debajo del capó ahora y cómo funcionó en el pasado.
Webmut
2
a partir de php7.2 utilizando el punto de referencia anterior, foreach sigue siendo el más rápido
billynoah
36

key($an_array) te dará la primera clave

editar por Blixt: debe llamar reset($array);antes key($an_array)para restablecer el puntero al comienzo de la matriz.

jimyi
fuente
77
Recuerde que el puntero de la matriz puede no estar en el primer elemento, vea mi respuesta.
Blixt
Creo que esta respuesta ayudará a mi caso sin restablecer porque primero me estoy asegurando de que la matriz tenga solo un elemento. Gracias
groovenectar
23

Tu podrías intentar

array_keys($data)[0]
Tapón
fuente
22

Para 2018+ a

partir de PHP 7.3, hay una array_key_first()función que logra exactamente esto:

$array = ['foo' => 'lorem', 'bar' => 'ipsum'];
$firstKey = array_key_first($array); // 'foo'

La documentación está disponible aquí . 😉

ivanaugustobd
fuente
21
list($firstKey) = array_keys($yourArray);
Sergiy Sokolenko
fuente
2
Probablemente este no sea el más eficiente.
Yada
3
@Yada, sí, pero esto puede ser notable en casos raros; en la mayoría de los casos, la legibilidad y la mantenibilidad son de mucha mayor importancia; y también prefiero una solución que no mute los objetos / matrices originales: por ejemplo, reset ($ ar); $ clave = clave ($ ar); - no siempre es una buena idea, prefiero elegir la solución de MartyIX que es más concisa que la mía, por ejemplo: array_keys ($ ar) [0];
Sergiy Sokolenko
20

Si la eficiencia no es tan importante para usted, puede usarla array_keys($yourArray)[0]en PHP 5.4 (y superior).

Ejemplos:

# 1
$arr = ["my" => "test", "is" => "best"];    
echo array_keys($arr)[0] . "\r\n"; // prints "my"


# 2
$arr = ["test", "best"];
echo array_keys($arr)[0] . "\r\n"; // prints "0"

# 3
$arr = [1 => "test", 2 => "best"];
echo array_keys($arr)[0] . "\r\n"; // prints "1"

La ventaja sobre la solución:

list($firstKey) = array_keys($yourArray);

es que puede pasar array_keys($arr)[0]como parámetro de función (es decir doSomething(array_keys($arr)[0], $otherParameter)).

HTH

Martin Vseticka
fuente
3
¿La array_keys($arr)[0]sintaxis es válida?
trante
55
Está en PHP 5.4. Se llama array dereferencing. Ver por ejemplo: schlueters.de/blog/archives/…
Martin Vseticka
@trante, es válido en todos los idiomas bajo el sol, excepto PHP <5.4.
Pacerier
13

Por favor encuentre lo siguiente:

$yourArray = array('first_key'=> 'First', 2, 3, 4, 5);
$keys   =   array_keys($yourArray);
echo "Key = ".$keys[0];

Ejemplo de trabajo

Alumno
fuente
12
$myArray = array(
    2 => '3th element',
    4 => 'first element',
    1 => 'second element',
    3 => '4th element'
);
echo min(array_keys($myArray)); // return 1
Hamidreza
fuente
1
@jurgemaister max()dosis no devuelve la primera clave de una matriz de asociación max return valor máximo de una lista o una matriz de elementos
Hamidreza
55
No es la solicitud de OP, pero es muy útil en algunas situaciones.
d.raev
9

Esto también podría ser una solución:

$yourArray = array('first_key'=> 'First', 2, 3, 4, 5);
$first_key = current(array_flip($yourArray));
echo $first_key;

Lo he probado y funciona.

Código de Trabajo .

Alumno
fuente
3
array_flip (): ¡Solo puede voltear los valores STRING e INTEGER!
Mauro
5

Para mejorar la solución de Webmut , he agregado la siguiente solución:

$firstKey = array_keys(array_slice($array, 0, 1, TRUE))[0];

El resultado para mí en PHP 7.1 es:

foreach to get first key and value: 0.048566102981567 seconds 
reset+key to get first key and value: 0.11727809906006 seconds 
reset+key to get first key: 0.11707186698914 seconds 
array_keys to get first key: 0.53917098045349 seconds 
array_slice to get first key: 0.2494580745697 seconds 

Si hago esto para una matriz de tamaño 10000, entonces los resultados se convierten

foreach to get first key and value: 0.048488140106201 seconds 
reset+key to get first key and value: 0.12659382820129 seconds 
reset+key to get first key: 0.12248802185059 seconds 
array_slice to get first key: 0.25442600250244 seconds 

El método array_keys agota el tiempo de espera en 30 segundos (con solo 1000 elementos, el tiempo para el resto fue casi el mismo, pero el método array_keys tuvo aproximadamente 7.5 segundos).

PrinsEdje80
fuente
3
 $arr = array('key1'=>'value1','key2'=>'value2','key3'=>'key3');
 list($first_key) = each($arr);
 print $first_key;
 // key1
voodoo417
fuente
3

La mejor manera que funcionó para mí fue

array_shift(array_keys($array))

array_keys obtiene una matriz de claves de la matriz inicial y luego array_shiftcorta de ella el primer valor del elemento. Necesitará PHP 5.4+ para esto.

Yuriy Petrovskiy
fuente
3

Esta es la forma más fácil que he encontrado. Rápido y solo dos líneas de código :-D

$keys = array_keys($array);
echo $array[$keys[0]];
Salvi Pascual
fuente
2

php73:

$array = ['a' => '..', 'b' => '..'];

array_key_first($array); // 'a'
array_key_last($array); // 'b';

http://php.net/manual/en/function.array-key-first.php

Benjamin Beganović
fuente
1
Incluir una explicación realmente ayuda a mejorar la calidad de tu publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código
MichaelvE,
0

Una frase:

$array = array('key1'=>'value1','key2'=>'value2','key3'=>'key3');
echo key( array_slice( $array, 0, 1, true ) );

# echos 'key1'
Kohjah Breese
fuente
0

Hoy tuve que buscar la primera clave de mi matriz devuelta por una solicitud POST. (Y tenga en cuenta el número de un id de formulario, etc.)

Bueno, he encontrado esto: devolver la primera clave de la matriz asociativa en PHP

http://php.net/key

He hecho esto y funciona.

    $data = $request->request->all();
    dump($data);
    while ($test = current($data)) {
        dump($test);
        echo key($data).'<br />';die();
        break;
    }

Tal vez sea eco 15min de otro chico. CYA.

Roupioz Clemente
fuente
-2

Puedes jugar con tu matriz

$daysArray = array('Monday', 'Tuesday', 'Sunday');
$day = current($transport); // $day = 'Monday';
$day = next($transport);    // $day = 'Tuesday';
$day = current($transport); // $day = 'Tuesday';
$day = prev($transport);    // $day = 'Monday';
$day = end($transport);     // $day = 'Sunday';
$day = current($transport); // $day = 'Sunday';

Para obtener el primer elemento de la matriz que puede usar currenty para el último elemento puede usarend

Editar

Solo por el hecho de no obtener más votos por la respuesta, puede convertir su clave en valor usando array_keysy usando como se muestra arriba.

Priyank
fuente
1
Estos son valores, no claves.
Victor Schröder