Obtenir la première clé dans un tableau associatif (éventuellement)?

757

Quelle est la meilleure façon de déterminer la première clé d'un tableau éventuellement associatif? Mon premier a pensé à juste foreach le tableau, puis le casser immédiatement, comme ceci:

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

Ainsi, avoir $ key contient la première clé, mais cela semble inefficace. Quelqu'un at-il une meilleure solution?

Alex S
la source
4
Pourquoi est inefficace foreach?
Emilio Gort
2
Par rapport à toutes les réponses, foreach est toujours le FIDDLE le plus rapide, PHP 5.3 , mon test localhost sur PHP 5.5 montre que la différence est légèrement en faveur de foreach.
Danijel
3
@Danijel, foreachest sémantiquement faux.
Pacerier
2
@AlexS, Soit each($arr)['key']ou each($arr)[0]fonctionnerait.
Pacerier
1
@Danijel Pas plus ... clé 0.01070.0217
:,

Réponses:

1338

Mise à jour 2019

À partir de PHP 7.3 , il existe une nouvelle fonction intégrée appelée array_key_first()qui récupérera la première clé du tableau donné sans réinitialiser le pointeur interne. Consultez la documentation pour plus d'informations.


Vous pouvez utiliser resetet key:

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

C'est essentiellement le même que votre code initial, mais avec un peu moins de surcharge, et c'est plus évident ce qui se passe.

N'oubliez pas d'appeler reset, sinon vous obtiendrez l'une des clés du tableau. Vous pouvez également utiliser endau lieu de resetpour obtenir la dernière clé.

Si vous vouliez que la clé obtienne la première valeur, la resetrenvoie en fait:

$first_value = reset($array);

Il y a cependant un cas particulier à surveiller (vérifiez d'abord la longueur du tableau):

$arr1 = array(false);
$arr2 = array();
var_dump(reset($arr1) === reset($arr2)); // bool(true)
Blixt
la source
141
En remarque, reset()il arrive également de retourner le premier élément (valeur, pas clé) de n'importe quel tableau, ce qui peut également être utile.
devios1
5
Il y a un commentaire dans la documentation pour reset()dire Don't use reset () `pour obtenir la première valeur d'un tableau associatif. Cela fonctionne très bien pour les vrais tableaux mais fonctionne de manière inattendue sur les objets Iterator. bugs.php.net/bug.php?id=38478 `Est-ce toujours vrai? Je suis confus
Dmitry Pashkevich
13
@DmitryPashkevich: Ne vous inquiétez pas de ce commentaire. Ils ne parlent pas d' arrayobjets, mais d'objets personnalisés (qui ne sont pas de véritables tableaux). Je suppose qu'ils ont confondu la différence dans les structures de données, mais en gros, resetrenvoie la valeur de la première "clé", qui pour les objets serait $propdans l'exemple donné dans le rapport "bug", mais pour un tableau la première clé. Alors ne vous inquiétez pas, tant que vous utilisez de vrais tableaux (créés avec array(…)), vous n'aurez pas de problème.
Blixt
2
Il convient de mentionner que end () et reset () ont un effet secondaire. Cependant, la plupart du code dans le monde ne dépend pas du pointeur interne se trouvant n'importe où, donc ce n'est généralement pas un problème.
donquixote
1
@ user3019105 Il n'y a qu'un seul pointeur interne par tableau, ce qui signifie que si un code en dehors de votre fonction le change (en appelant next, reset, endou en boucle à travers le réseau), vous ne recevrez pas la valeur attendue lorsque vous appelez key. Alors oui, appelez toujours resetavant d'utiliser keypour être sûr d'obtenir ce que vous voulez.
Blixt
80

array_keysrenvoie un tableau de clés. Prenez la première entrée. Alternativement, vous pouvez appeler resetle tableau, puis par la suite key. Cette dernière approche est probablement légèrement plus rapide (même si je ne l'ai pas testée), mais elle a pour effet secondaire de réinitialiser le pointeur interne.

troelskn
la source
52
Juste une note (tardive) pour les futurs lecteurs de ceci: Cette dernière approche n'est pas seulement "légèrement" plus rapide. Il y a une grande différence entre itérer un tableau entier, stocker chaque clé dans un autre tableau nouvellement créé et demander la première clé d'un tableau sous forme de chaîne.
Blixt
3
Pourquoi est inefficace foreach comme l'op a dans la question comparer à toutes ces réponses?
Emilio Gort
5
@EmilioGort Bonne question. Je ne pense pas qu'il y ait de différence dans les performances de foreach+ breaket reset+ en keyfait. Mais le premier a l'air plutôt bizarre, donc pour les problèmes stylistiques, je préférerais le second.
troelskn
@EmilioGort: Afaik, foreach () copie le tableau en interne. Nous pouvons donc supposer qu'il est plus lent. (Ce serait bien si quelqu'un pouvait le confirmer)
donquixote
3
@donquixote Je ne sais pas avec certitude, mais en supposant que c'est un tableau régulier (et non un objet implémentant une sorte ou une interface Iterator), je suis assez sûr de foreachne pas créer une copie interne pour cela, mais simplement itérer un pointeur , similaire à l'utilisation du niveau le plus bas next, currentetc.
troelskn
54

Chose intéressante, la boucle foreach est en fait le moyen le plus efficace de le faire.

Étant donné que le PO a spécifiquement posé des questions sur l'efficacité, il convient de souligner que toutes les réponses actuelles sont en fait beaucoup moins efficaces qu'un foreach.

J'ai fait un benchmark avec php 5.4, et la méthode reset / key pointer (réponse acceptée) semble être environ 7 fois plus lente qu'une foreach. D'autres approches manipulant l'ensemble du tableau (array_keys, array_flip) sont évidemment encore plus lentes que cela et deviennent bien pires lorsque vous travaillez avec un grand tableau.

Foreach n'est pas du tout inefficace, n'hésitez pas à l'utiliser!

Modifier 2015-03-03:

Des scripts de référence ont été demandés, je n'ai pas les originaux mais j'ai fait de nouveaux tests à la place. Cette fois, j'ai trouvé le foreach seulement deux fois plus rapide que reset / key. J'ai utilisé un tableau de 100 clés et j'ai exécuté chaque méthode un million de fois pour obtenir une différence notable, voici le code du benchmark 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 />";

Sur mon php 5.5, cela produit:

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
la source
3
Avez-vous les repères quelque part. Comme la façon dont vous avez testé, etc. Quoi qu'il en soit, merci de les avoir exécutés!
grippe
Je voudrais souligner le fait que le même tableau est utilisé tout au long du test. Je pense que ce fait influence considérablement l'approche foreach. Comme @donquixote l'a mentionné dans le commentaire d'une réponse ci-dessus - foreach copie en interne le tableau. Je peux imaginer que cette copie est réutilisée lors de l'exécution de la référence, car le fait d'éviter la copie de tableau améliore les performances uniquement dans ce test.
Jarda
2
@Jarda Depuis php7, foreachne copie jamais le tableau sauf si vous le modifiez directement à l'intérieur de la boucle foreach. Sur php5, la structure du tableau peut être copiée dans certains cas (lorsque son refcount> 1) et vous avez en fait raison, cela pourrait avoir une influence significative. Heureusement, il n'y a rien à craindre sur php7, où ce problème a été résolu. Voici une excellente lecture à la fois sur la façon dont foreach fonctionne sous le capot maintenant et comment cela a fonctionné dans le passé.
Webmut
2
à partir de php7.2 en utilisant le benchmark ci-dessus, foreach est toujours le plus rapide
billynoah
36

key($an_array) vous donnera la première clé

edit per Blixt: vous devez appeler reset($array);avant key($an_array)pour réinitialiser le pointeur au début du tableau.

jimyi
la source
7
N'oubliez pas que le pointeur du tableau peut ne pas être au premier élément, voir ma réponse.
Blixt
Je pense que cette réponse aidera mon cas sans réinitialisation car je m'assure d'abord que le tableau n'a qu'un seul élément. Merci
groovenectar
23

Tu pourrais essayer

array_keys($data)[0]
Bouchon
la source
22

Pour 2018+

À partir de PHP 7.3, il existe une array_key_first()fonction qui réalise exactement ceci:

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

La documentation est disponible ici . 😉

ivanaugustobd
la source
21
list($firstKey) = array_keys($yourArray);
Sergiy Sokolenko
la source
2
Ce n'est probablement pas le plus efficace.
Yada
3
@Yada, oui, mais cela peut être perceptible dans de rares cas; dans la plupart des cas, la lisibilité et la maintenabilité sont beaucoup plus importantes; et je préfère également une solution qui ne mute pas les objets / tableaux originaux: par exemple reset ($ ar); $ clé = clé ($ ar); - n'est pas toujours une bonne idée, je préfère la solution de MartyIX qui est plus concise que la mienne, par exemple: array_keys ($ ar) [0];
Sergiy Sokolenko
20

Si l'efficacité n'est pas si importante pour vous, vous pouvez l'utiliser array_keys($yourArray)[0]en PHP 5.4 (et supérieur).

Exemples:

# 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"

L'avantage sur la solution:

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

c'est que vous pouvez passer array_keys($arr)[0]comme paramètre de fonction (ie doSomething(array_keys($arr)[0], $otherParameter)).

HTH

Martin Vseticka
la source
3
La array_keys($arr)[0]syntaxe est-elle valide?
trante
5
C'est en PHP 5.4. Ça s'appelle array dereferencing. Voir par exemple: schlueters.de/blog/archives/…
Martin Vseticka
@trante, il est valable dans toutes les langues sous le soleil sauf PHP <5.4.
Pacerier
13

Veuillez trouver les éléments suivants:

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

Exemple de travail:

Élève
la source
12
$myArray = array(
    2 => '3th element',
    4 => 'first element',
    1 => 'second element',
    3 => '4th element'
);
echo min(array_keys($myArray)); // return 1
Hamidreza
la source
1
@jurgemaister max()dose ne renvoie pas la première clé d'un tableau d'assoc. max return valeur maximale d'une liste ou d'un tableau éléments
Hamidreza
5
Pas la demande OP, mais très utile dans certaines situations.
d.raev
9

Cela pourrait également être une solution:

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

Je l'ai testé et ça marche.

Code de travail .

Élève
la source
3
array_flip (): ne peut inverser que les valeurs STRING et INTEGER!
Mauro
5

Pour améliorer la solution de Webmut , j'ai ajouté la solution suivante:

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

La sortie pour moi sur PHP 7.1 est:

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 je fais cela pour un tableau de taille 10000, les résultats deviennent

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 

La méthode array_keys expire à 30 secondes (avec seulement 1000 éléments, le timing pour le reste était à peu près le même, mais la méthode array_keys avait environ 7,5 secondes).

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

La meilleure façon qui a fonctionné pour moi était

array_shift(array_keys($array))

array_keys obtient le tableau de clés du tableau initial puis en array_shiftcoupe la première valeur d'élément. Vous aurez besoin de PHP 5.4+ pour cela.

Yuriy Petrovskiy
la source
3

C'est le moyen le plus simple que j'aie jamais trouvé. Rapide et seulement deux lignes de code :-D

$keys = array_keys($array);
echo $array[$keys[0]];
Salvi Pascual
la source
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ć
la source
1
Inclure une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code
MichaelvE
0

Un one-liner:

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

# echos 'key1'
Kohjah Breese
la source
0

Aujourd'hui, j'ai dû rechercher la première clé de mon tableau renvoyée par une requête POST. (Et notez le numéro d'un identifiant de formulaire, etc.)

Eh bien, j'ai trouvé ceci: Retourne la première clé du tableau associatif en PHP

http://php.net/key

J'ai fait ça, et ça marche.

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

Peut-être que ça va éco 15min d'un autre gars. CYA.

Roupioz Clement
la source
-2

Vous pouvez jouer avec votre tableau

$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';

Pour obtenir le premier élément du tableau, vous pouvez utiliser currentet pour le dernier élément, vous pouvez utiliserend

Éditer

Juste pour ne plus obtenir de votes négatifs pour la réponse, vous pouvez convertir votre clé en valeur en utilisant array_keyset utiliser comme indiqué ci-dessus.

Priyank
la source
1
Ce sont des valeurs, pas des clés.
Victor Schröder