Zdobądź pierwszy klucz w (ewentualnie) tablicy asocjacyjnej?

756

Jaki jest najlepszy sposób ustalenia pierwszego klucza w potencjalnie asocjacyjnej tablicy? Najpierw pomyślałem, że po prostu przewidziełem tablicę, a potem natychmiast ją złamałem, tak:

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

Zatem posiadanie klucza $ zawiera pierwszy klucz, ale wydaje się to nieefektywne. Czy ktoś ma lepsze rozwiązanie?

Alex S.
źródło
4
Dlaczego nieefektywne foreach?
Emilio Gort
2
W porównaniu do wszystkich odpowiedzi, foreach jest nadal najszybszym FIDDLE, PHP 5.3 , mój test localhost na PHP 5.5 pokazuje, że różnica jest nieco na korzyść foreach.
Danijel
3
@Danijel, foreachjest semantycznie błędny.
Pacerier
2
@AlexS, albo each($arr)['key']albo each($arr)[0]będzie działać.
Pacerier
1
@Danijel Już nie ... klucz 0.01070.0217
:,

Odpowiedzi:

1337

Aktualizacja 2019

Począwszy od PHP 7.3 pojawiła się nowa wbudowana funkcja o nazwie, array_key_first()która pobierze pierwszy klucz z podanej tablicy bez resetowania wewnętrznego wskaźnika. Sprawdź dokumentację, aby uzyskać więcej informacji.


Możesz użyć reseti key:

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

Zasadniczo jest taki sam jak początkowy kod, ale ma nieco mniejszy narzut i bardziej oczywiste jest, co się dzieje.

Pamiętaj tylko, aby zadzwonić reset, w przeciwnym razie możesz dostać dowolny klucz z tablicy. Możesz także użyć endzamiast, resetaby uzyskać ostatni klucz.

Jeśli chcesz, aby klucz uzyskał pierwszą wartość, resetfaktycznie ją zwraca:

$first_value = reset($array);

Jest jednak jeden szczególny przypadek, na który należy uważać (więc najpierw sprawdź długość tablicy):

$arr1 = array(false);
$arr2 = array();
var_dump(reset($arr1) === reset($arr2)); // bool(true)
Blixt
źródło
141
Na marginesie, reset()zdarza się również, że zwraca pierwszy element (wartość, a nie klucz) z dowolnej tablicy, co również może być przydatne.
devios1
5
W dokumentacji jest komentarz do reset()powiedzenia Don't use reset () `, aby uzyskać pierwszą wartość tablicy asocjacyjnej. Działa świetnie dla prawdziwych tablic, ale działa nieoczekiwanie na obiektach Iterator. bugs.php.net/bug.php?id=38478 `Czy to nadal prawda? Jestem zdezorientowany
Dmitrij Paszkiewicz
13
@DmitryPashkevich: Nie przejmuj się tym komentarzem. Nie mówią o arrayobiektach, ale o obiektach niestandardowych (które nie są rzeczywistymi tablicami). Sądzę, że pomylili różnice w strukturach danych, ale w zasadzie resetzwraca wartość pierwszego „klucza”, który dla obiektów byłby $propw przykładzie podanym w raporcie „błędu”, ale dla tablicy pierwszy klucz. Więc nie martw się, dopóki używasz prawdziwych tablic (utworzonych przy pomocy array(…)), nie będziesz mieć problemu.
Blixt,
2
Należy wspomnieć, że end () i reset () mają efekt uboczny. Jednak większość kodu na świecie nie polega na tym, że wewnętrzny wskaźnik jest nigdzie, więc na ogół nie stanowi to problemu.
donquixote
1
@ user3019105 Jest tylko jeden wewnętrzny wskaźnik tablicy na, co oznacza, że jeśli kod poza funkcją zmienia go (poprzez wywołanie next, reset, endlub pętli w tablicy), nie dostaniesz wartość oczekiwaną podczas rozmowy key. Tak, zawsze zadzwoń resetprzed użyciem, keyaby upewnić się, że dostaniesz to, czego chcesz.
Blixt,
80

array_keyszwraca tablicę kluczy. Weź pierwszy wpis. Alternatywnie możesz wywołać resettablicę, a następnie key. To drugie podejście jest prawdopodobnie nieco szybsze (nie testowałem go), ale ma efekt uboczny resetowania wewnętrznego wskaźnika.

troelskn
źródło
52
Tylko (późna) uwaga dla przyszłych czytelników: to drugie podejście jest nie tylko „nieco” szybsze. Istnieje duża różnica między iteracją całej tablicy, przechowywaniem każdego klucza w innej nowo utworzonej tablicy, a żądaniem pierwszego klucza tablicy jako łańcucha.
Blixt,
3
Dlaczego nieefektywne foreach, jak operacja w pytaniu, porównuje do wszystkich tych odpowiedzi?
Emilio Gort
5
@EmilioGort Dobre pytanie. Nie sądzę, żeby faktycznie istniała różnica w wydajności foreach+ breaki reset+ key. Ale ten pierwszy wygląda dość dziwnie, więc ze względów stylistycznych wolałbym ten drugi.
troelskn
@EmilioGort: Afaik, foreach () kopiuje tablicę wewnętrznie. Możemy więc założyć, że jest wolniejszy. (Byłoby miło, gdyby ktoś mógł to potwierdzić)
donquixote
3
@donquixote Nie wiem na pewno, ale zakładając, że jest to zwykła tablica (a nie obiekt implementujący jakiś interfejs lub interfejs Iteratora), jestem pewien, foreachże nie tworzy dla niej wewnętrznej kopii, a jedynie iteruje wskaźnik , podobnie jak przy użyciu więcej niskiego poziomu next, currentitd
troelskn
54

Co ciekawe, pętla foreach jest w rzeczywistości najbardziej efektywnym sposobem na zrobienie tego.

Ponieważ PO konkretnie zapytał o efektywność, należy zauważyć, że wszystkie obecne odpowiedzi są w rzeczywistości znacznie mniej skuteczne niż foreach.

Zrobiłem test porównawczy na php 5.4, a metoda reset / wskaźnik klucza (zaakceptowana odpowiedź) wydaje się być około 7 razy wolniejsza niż foreach. Inne podejścia do manipulowania całą tablicą (array_keys, array_flip) są oczywiście jeszcze wolniejsze i stają się znacznie gorsze podczas pracy z dużą tablicą.

Foreach wcale nie jest nieefektywny, możesz go używać!

Edytuj 2015-03-03:

Zażądano skryptów testowych, nie mam oryginalnych, ale wykonałem kilka nowych testów. Tym razem znalazłem foreach tylko około dwa razy szybciej niż reset / klucz. Użyłem tablicy 100-klawiszowej i każdą metodę milion razy uruchomiłem, aby uzyskać zauważalną różnicę, oto kod prostego testu porównawczego:

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

Na moim php 5.5 ten wynik:

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 + klucz http://3v4l.org/b4DrN/perf#tabs
foreach http://3v4l.org/gRoGD/perf#tabs

Webmut
źródło
3
Czy masz gdzieś wzorce. Podobnie jak w przypadku testowania itp. W każdym razie dziękuję za ich uruchomienie!
grypa
Chciałbym zwrócić uwagę na fakt, że przez cały test użyto tej samej tablicy. Myślę, że fakt ten ma znaczący wpływ na podejście Foreach. Jak wspomniano w komentarzu @donquixote do niektórych odpowiedzi powyżej - foreach wewnętrznie kopiuje tablicę. Mogę sobie wyobrazić, że ta kopia jest ponownie używana podczas uruchamiania testu porównawczego, ponieważ unikanie kopiowania tablicy zwiększa wydajność tylko w tym teście.
Jarda
2
@Jarda Począwszy od php7, foreachnigdy nie kopiuj tablicy, chyba że zmodyfikujesz ją bezpośrednio w pętli foreach. Na php5 struktura tablicy może być kopiowana w niektórych przypadkach (gdy jej przelicznik> 1) i masz rację, może to mieć znaczący wpływ. Na szczęście nie ma się czym martwić na php7, gdzie problem został rozwiązany. Oto świetna lektura zarówno o tym, jak działa foreach teraz, jak i o przeszłości.
Webmut,
2
od php7.2 przy użyciu powyższego testu porównawczego, Foreach jest wciąż najszybszy
billynoah
36

key($an_array) da ci pierwszy klucz

edit per Blixt: powinieneś zadzwonić reset($array);przed, key($an_array)aby zresetować wskaźnik do początku tablicy.

jimyi
źródło
7
Pamiętaj, że wskaźnik tablicy może nie znajdować się na pierwszym elemencie, patrz moja odpowiedź.
Blixt
Myślę, że ta odpowiedź pomoże mojej sprawie bez resetu, ponieważ najpierw upewniam się, że tablica ma tylko jeden element. Dzięki
groovenectar,
23

Możesz spróbować

array_keys($data)[0]
Korek
źródło
22

W wersji 2018+

Począwszy od wersji PHP 7.3 istnieje array_key_first()funkcja, która osiąga dokładnie to:

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

Dokumentacja jest dostępna tutaj . 😉

ivanaugustobd
źródło
21
list($firstKey) = array_keys($yourArray);
Sergiy Sokolenko
źródło
2
To chyba nie jest najbardziej wydajne.
Yada
3
@Yada, tak, ale może to być zauważalne w rzadkich przypadkach; w większości przypadków czytelność i łatwość konserwacji mają znacznie większe znaczenie; i wolę także rozwiązanie, które nie mutuje oryginalnych obiektów / tablic: np. reset ($ ar); $ klucz = klucz ($ ar); - nie zawsze jest dobrym pomysłem, wolałbym wybrać rozwiązanie MartyIX, które jest bardziej zwięzłe niż moje, np .: array_keys ($ ar) [0];
Sergiy Sokolenko
20

Jeśli wydajność nie jest dla Ciebie tak ważna, możesz użyć array_keys($yourArray)[0]w PHP 5.4 (i wyższych).

Przykłady:

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

Przewaga nad rozwiązaniem:

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

jest to, że możesz przekazać array_keys($arr)[0]jako parametr funkcji (tj doSomething(array_keys($arr)[0], $otherParameter).).

HTH

Martin Vseticka
źródło
3
Czy array_keys($arr)[0]składnia jest poprawna?
trante
5
Jest w PHP 5.4. To się nazywa array dereferencing. Patrz na przykład: schlueters.de/blog/archives/…
Martin Vseticka
@trante, obowiązuje we wszystkich językach pod słońcem, z wyjątkiem PHP <5.4.
Pacerier
13

Proszę znaleźć następujące:

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

Przykład roboczy:

Uczeń
źródło
12
$myArray = array(
    2 => '3th element',
    4 => 'first element',
    1 => 'second element',
    3 => '4th element'
);
echo min(array_keys($myArray)); // return 1
Hamidreza
źródło
1
@ jurgemaister max()dawka nie zwraca pierwszego klucza tablicy assoc. maksymalny zwrot maksymalnej wartości listy lub elementów tablicy
Hamidreza
5
Nie żądanie OP, ale bardzo przydatne w niektórych sytuacjach.
d.raev
9

Może to być również rozwiązanie:

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

Przetestowałem to i działa.

Kodeks roboczy .

Uczeń
źródło
3
array_flip (): Może odwracać tylko wartości STRING i INTEGER!
Mauro
5

Aby ulepszyć rozwiązanie Webmut , dodałem następujące rozwiązanie:

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

Dane wyjściowe dla mnie w PHP 7.1 to:

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 

Jeśli zrobię to dla tablicy o rozmiarze 10000, wyniki będą

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 

Upłynął limit czasu metody array_keys po 30 sekundach (przy zaledwie 1000 elementów czas pozostałej części był mniej więcej taki sam, ale metoda array_keys miała około 7,5 sekundy).

PrinsEdje80
źródło
3
 $arr = array('key1'=>'value1','key2'=>'value2','key3'=>'key3');
 list($first_key) = each($arr);
 print $first_key;
 // key1
voodoo417
źródło
3

Najlepszy sposób, który dla mnie zadziałał, to

array_shift(array_keys($array))

array_keys pobiera tablicę kluczy z tablicy początkowej, a następnie array_shiftwycina z niej wartość pierwszego elementu. W tym celu potrzebujesz PHP 5.4+.

Jurij Pietrowski
źródło
3

To jest łatwiejszy sposób, jaki kiedykolwiek znalazłem. Szybki i tylko dwie linie kodu :-D

$keys = array_keys($array);
echo $array[$keys[0]];
Salvi Pascual
źródło
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ć
źródło
1
Dołączenie objaśnienia naprawdę pomaga poprawić jakość posta. Pamiętaj, że odpowiadasz na pytanie dla czytelników w przyszłości, a ci ludzie mogą nie znać powodów Twojej sugestii kodu
MichaelvE
0

Jednowarstwowy:

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

# echos 'key1'
Kohjah Breese
źródło
0

Dzisiaj musiałem poszukać pierwszego klucza mojej tablicy zwróconego przez żądanie POST. (I zanotuj numer identyfikatora formularza itp.)

Znalazłem to: Zwraca pierwszy klucz tablicy asocjacyjnej w PHP

http://php.net/key

Zrobiłem to i działa.

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

Może będzie to eko 15 minut od innego faceta. CYA.

Roupioz Clement
źródło
-2

Możesz grać ze swoją tablicą

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

Aby uzyskać pierwszy element tablicy, którego możesz użyć, currenta dla ostatniego elementu możesz użyćend

Edytować

Żeby nie otrzymywać więcej głosów za odpowiedź, możesz przekonwertować klucz na wartość, używając array_keysi wykorzystując, jak pokazano powyżej.

Priyank
źródło
1
To są wartości, a nie klucze.
Victor Schröder,