Ottieni la prima chiave in un array (forse) associativo?


757

Qual è il modo migliore per determinare la prima chiave in un array eventualmente associativo? Il mio primo pensiero è stato quello di prevedere l'array e poi di romperlo immediatamente, in questo modo:

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

Quindi avere $ key contiene la prima chiave, ma questo sembra inefficiente. Qualcuno ha una soluzione migliore?


4
Perché la foreach è inefficiente?
Emilio Gort,

2
Rispetto a tutte le risposte, foreach è ancora il FIDDLE più veloce , PHP 5.3 , il mio test localhost su PHP 5.5 mostra che la differenza è leggermente a favore di foreach.
Danijel,

3
@Danijel, foreachè semanticamente sbagliato.
Pacerier,

2
@AlexS, O each($arr)['key']o each($arr)[0]funzionerebbe.
Pacerier,

1
@Danijel Non più ... chiave 0.01070.0217
:,

Risposte:


1338

Aggiornamento 2019

A partire da PHP 7.3 , c'è una nuova funzione integrata chiamata array_key_first()che recupererà la prima chiave dall'array dato senza ripristinare il puntatore interno. Consulta la documentazione per ulteriori informazioni.


Puoi usare resete key:

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

È essenzialmente lo stesso del codice iniziale, ma con un po 'meno di sovraccarico, ed è più ovvio ciò che sta accadendo.

Ricorda solo di chiamare reset, altrimenti potresti ottenere uno dei tasti dell'array. Puoi anche usare endinvece di resetottenere l'ultima chiave.

Se si desidera che la chiave ottenga il primo valore, in resetrealtà lo restituisce:

$first_value = reset($array);

C'è un caso speciale da tenere d'occhio (quindi controlla prima la lunghezza dell'array):

$arr1 = array(false);
$arr2 = array();
var_dump(reset($arr1) === reset($arr2)); // bool(true)

141
Come nota a margine, reset()capita anche di restituire il primo elemento (valore, non chiave) di qualsiasi array, che può anche essere utile.
devios1,

5
C'è un commento nei documenti per reset()dire Don't use reset () `per ottenere il primo valore di un array associativo. Funziona alla grande con array veri ma funziona inaspettatamente su oggetti Iterator. bugs.php.net/bug.php?id=38478 `È ancora vero? Sono confuso
Dmitry Pashkevich il

13
@DmitryPashkevich: non preoccuparti per quel commento. Non stanno parlando di arrayoggetti, ma di oggetti personalizzati (che non sono matrici reali). Immagino che abbiano confuso la differenza nelle strutture dati, ma sostanzialmente resetrestituisce il valore della prima "chiave", che per gli oggetti sarebbe $propnell'esempio riportato nel rapporto "bug", ma per un array la prima chiave. Quindi non preoccuparti, finché utilizzi array reali (creati con array(…)), non avrai problemi.
Blixt,

2
Va notato che end () e reset () hanno un effetto collaterale. Tuttavia, la maggior parte del codice nel mondo non si basa sul fatto che il puntatore interno si trovi da nessuna parte, quindi questo generalmente non è un problema.
donquixote,

1
@ user3019105 C'è solo un puntatore interno per array, il che significa che se tutto il codice di fuori della funzione cambia (chiamando next, reset, endo scorrendo l'array), non sarà possibile ottenere il valore previsto quando si chiama key. Quindi sì, chiama sempre resetprima dell'uso keyper essere sicuro di ottenere ciò che desideri.
Blixt,

80

array_keysrestituisce una matrice di chiavi. Prendi la prima voce. In alternativa, è possibile chiamare resetl'array e successivamente key. Quest'ultimo approccio è probabilmente leggermente più veloce (Thoug non l'ho provato), ma ha l'effetto collaterale di ripristinare il puntatore interno.


52
Solo una nota (tardiva) per i futuri lettori di questo: quest'ultimo approccio non è solo "leggermente" più veloce. C'è una grande differenza tra l'iterazione di un intero array, la memorizzazione di ogni chiave in un altro array appena creato e la richiesta della prima chiave di un array come stringa.
Blixt,

3
Perché la ricerca inefficiente come l'operazione ha nella domanda è paragonabile a tutte queste risposte?
Emilio Gort,

5
@EmilioGort Buona domanda. Non penso che ci sia alcuna differenza nell'esecuzione di foreach+ breake reset+ in keyrealtà. Ma il primo sembra piuttosto strano, quindi per questioni stilistiche preferirei il secondo.
troelskn,

@EmilioGort: Afaik, foreach () copia l'array internamente. Quindi possiamo presumere che sia più lento. (Sarebbe bello se qualcuno potesse confermarlo)
donquixote

3
@donquixote Non lo so per certo, ma supponendo che sia un array normale (e non un oggetto che implementa un qualche tipo o un'interfaccia Iterator), sono abbastanza sicuro foreachche non crei una copia interna per esso, ma piuttosto semplicemente itera un puntatore , simile all'utilizzo del livello più basso next, currentecc.
troelskn,

54

È interessante notare che il ciclo foreach è in realtà il modo più efficiente per farlo.

Dato che il PO ha specificamente chiesto l'efficienza, si dovrebbe sottolineare che tutte le risposte attuali sono in effetti molto meno efficienti di una ricerca.

Ho fatto un benchmark su questo con php 5.4 e il metodo di puntatore reset / tasto (risposta accettata) sembra essere circa 7 volte più lento di un foreach. Altri approcci che manipolano l'intero array (array_keys, array_flip) sono ovviamente anche più lenti di così e peggiorano molto quando si lavora con un array di grandi dimensioni.

Foreach non è affatto inefficiente, sentiti libero di usarlo!

Modifica 03-03-2015:

Sono stati richiesti script di benchmark, non ho quelli originali, ma ho fatto alcuni nuovi test. Questa volta ho trovato foreach solo circa due volte più veloce di reset / key. Ho usato un array di 100 tasti ed eseguito ogni metodo un milione di volte per ottenere una notevole differenza, ecco il codice del semplice benchmark:

$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 />";

Sul mio php 5.5 questo 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 + chiave http://3v4l.org/b4DrN/perf#tabs
foreach http://3v4l.org/gRoGD/perf#tabs


3
Hai i benchmark da qualche parte. Ti piace come hai provato, ecc. Comunque, grazie per averli eseguiti!
influenza

Vorrei sottolineare il fatto che esiste l'intero array utilizzato durante l'intero test. Penso che questo fatto influenzi significativamente l'approccio foreach. Come @donquixote ha menzionato nel commento ad alcune risposte sopra - foreach copia internamente l'array. Posso immaginare che questa copia venga riutilizzata mentre si esegue il benchmark poiché evitare la copia di array migliora le prestazioni solo durante questo test.
Jarda,

2
@Jarda A partire da php7, foreachnon copia mai l'array a meno che non lo modifichi direttamente all'interno del ciclo foreach. Su php5 la struttura dell'array potrebbe essere copiata in alcuni casi (quando il suo refcount> 1) e in realtà hai ragione, potrebbe avere un'influenza significativa lì. Fortunatamente non c'è nulla di cui preoccuparsi su php7, dove questo problema è stato risolto. Ecco un'ottima lettura sia su come funziona foreach ora sotto il cofano sia su come ha funzionato in passato.
Webmut,

2
a partire da php7.2 usando il benchmark sopra, foreach è ancora il più veloce
billynoah

36

key($an_array) ti darà la prima chiave

modifica per Blixt: è necessario chiamare reset($array);prima key($an_array)di ripristinare il puntatore all'inizio dell'array.


7
Ricorda che il puntatore dell'array potrebbe non essere al primo elemento, vedi la mia risposta.
Blixt,

Penso che questa risposta possa aiutare il mio caso senza reimpostare perché per prima cosa mi assicuro che l'array abbia un solo elemento. Grazie
groovenectar,


22

Per il 2018+

A partire da PHP 7.3, esiste una array_key_first()funzione che ottiene esattamente questo:

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

La documentazione è disponibile qui . 😉


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

2
Questo probabilmente non è il più efficiente.
Yada,

3
@Yada, sì, ma questo potrebbe essere evidente in rari casi; nella maggior parte dei casi la leggibilità e la manutenibilità rivestono un'importanza molto maggiore; e preferisco anche una soluzione che non muta gli oggetti / le matrici originali: ad es. reset ($ ar); $ key = key ($ ar); - non è sempre una buona idea, preferirei scegliere la soluzione di MartyIX che è più concisa della mia, ad esempio: array_keys ($ ar) [0];
Sergiy Sokolenko,

20

Se l'efficienza non è così importante per te, puoi usarla array_keys($yourArray)[0]in PHP 5.4 (e versioni successive).

Esempi:

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

Il vantaggio rispetto alla soluzione:

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

è che puoi passare array_keys($arr)[0]come parametro di funzione (esdoSomething(array_keys($arr)[0], $otherParameter) .).

HTH


3
La array_keys($arr)[0]sintassi è valida?
trante,

5
È in PHP 5.4. Si chiama array dereferencing. Vedi ad esempio: schlueters.de/blog/archives/…
Martin Vseticka,

@trante, è valido in tutte le lingue sotto il sole tranne PHP <5.4.
Pacerier,

13

Si prega di trovare quanto segue:

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

Esempio di lavoro:


12
$myArray = array(
    2 => '3th element',
    4 => 'first element',
    1 => 'second element',
    3 => '4th element'
);
echo min(array_keys($myArray)); // return 1

1
La max()dose di @jurgemaister non restituisce la prima chiave di un array assoc. valore massimo restituito valore massimo di un elenco o di un array
Hamidreza,

5
Non è la richiesta OP, ma molto utile in alcune situazioni.
d.raev,

9

Questa potrebbe anche essere una soluzione:

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

L'ho provato e funziona.

Codice di lavoro .


3
array_flip (): può solo capovolgere i valori STRING e INTEGER!
Mauro

5

Per migliorare la soluzione di Webmut , ho aggiunto la seguente soluzione:

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

L'output per me su PHP 7.1 è:

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 

Se lo faccio per un array di dimensioni 10000, i risultati diventano

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 

Il metodo array_keys scade a 30 secondi (con solo 1000 elementi, i tempi per il resto erano più o meno gli stessi, ma il metodo array_keys aveva circa 7,5 secondi).


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

3

Il modo migliore che ha funzionato per me è stato

array_shift(array_keys($array))

array_keys ottiene la matrice di chiavi dalla matrice iniziale e quindi array_shifttaglia da essa il primo valore dell'elemento. Per questo avrai bisogno di PHP 5.4+.


3

Questo è il modo più semplice che avessi mai trovato. Veloce e solo due righe di codice :-D

$keys = array_keys($array);
echo $array[$keys[0]];


0

Una fodera:

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

# echos 'key1'


-2

Puoi giocare con il tuo array

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

Per ottenere il primo elemento dell'array è possibile utilizzare currente per l'ultimo elemento è possibile utilizzareend

modificare

Solo per non avere più voti negativi per la risposta, puoi convertire la chiave in valore usando array_keyse usando come mostrato sopra.


1
Questi sono valori, non chiavi.
Victor Schröder,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.