Отримати перший ключ у (можливо) асоціативному масиві?


756

Який найкращий спосіб визначити перший ключ у можливо асоціативному масиві? Я спершу подумав, що це просто передбачити масив, а потім негайно розбити його, як це:

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

Таким чином, маючи $ ключ, міститься перший ключ, але це здається неефективним. Хтось має краще рішення?


4
Чому неефективне передбачення?
Еміліо Горт

2
У порівнянні з усіма відповідями, передбачення все ще є найшвидшим FIDDLE, PHP 5.3 , мій тест localhost на PHP 5.5 показує, що різниця дещо на користь foreach.
Даніель

3
@Danijel, foreachсемантично помиляється.
Pacerier

2
@ Алекс, each($arr)['key']або each($arr)[0]працюватиме.
Pacerier

1
@Danijel Більше не ... ключ:, 0.0107foreach:0.0217
SeanJA

Відповіді:


1337

Оновлення 2019 року

Починаючи з PHP 7.3 , є нова вбудована функція, array_key_first()яка називається, яка отримає перший ключ із заданого масиву, не скидаючи внутрішній покажчик. Перегляньте документацію для отримання додаткової інформації.


Ви можете використовувати resetта key:

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

Це по суті те саме, що і ваш початковий код, але з трохи меншими накладними витратами, і більш очевидно, що відбувається.

Просто не забудьте зателефонувати reset, інакше ви можете отримати будь-який з ключів у масиві. Ви також можете використовувати endзамість, resetщоб отримати останній ключ.

Якщо ви хотіли, щоб ключ отримав перше значення, resetнасправді повертає його:

$first_value = reset($array);

Існує один особливий випадок, на який слід звернути увагу (тому спочатку перевірте довжину масиву):

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

141
Як бічна примітка, reset()також буває повернути перший елемент (значення, а не ключ) будь-якого масиву, який також може бути зручним.
devios1

5
Там же коментар в Документах reset()кажучи Don't use скидання () ` , щоб отримати перше значення асоціативного масиву. Він чудово працює для справжніх масивів, але несподівано працює на об'єктах Iterator. bugs.php.net/bug.php?id=38478 `Це все-таки правда? Я розгублений
Дмитро Пашкевич

13
@DmitryPashkevich: Не хвилюйтеся з приводу цього коментаря. Вони говорять не про arrayоб'єкти, а про власні об’єкти (які не є фактичними масивами). Я думаю, вони отримали різницю в структурах даних заплутаною, але в основному resetповертає значення першого "ключа", який для об'єктів буде $propу прикладі, наведеному у звіті про помилку, а для масиву - перший ключ. Тому не хвилюйтеся, доки ви не використовуєте справжні масиви (створені за допомогою array(…)), у вас не виникне проблем.
Blixt

2
Слід зазначити, що закінчення () та скидання () мають побічну дію. Однак більшість кодів у світі не покладається на те, що внутрішній покажчик знаходиться десь, тому це, як правило, не є проблемою.
donquixote

1
@ User3019105 Існує тільки один внутрішній покажчик на масив, а це означає , що якщо якийсь - або код за межами функції змінює його (по телефону next, reset, endабо наскрізним через масив), ви не отримаєте очікуване значення при виклику key. Так що так, завжди телефонуйте resetперед використанням, keyщоб бути впевненим, що отримаєте те, що хочете.
Blixt

80

array_keysповертає масив ключів. Зробіть перший запис. Крім того, ви можете зателефонувати resetна масив, а згодом key. Останній підхід, мабуть, трохи швидший (Thoug, я його не перевіряв), але він має побічний ефект від скидання внутрішнього покажчика.


52
Лише (пізня) примітка для майбутніх читачів цього: Останній підхід не просто «трохи» швидший. Існує велика різниця між ітерацією всього масиву, зберіганням кожного ключа в іншому новоствореному масиві та запитом першого ключа масиву як рядка.
Blixt

3
Чому неефективне передбачення в порівнянні з усіма цими відповідями?
Еміліо Горт

5
@EmilioGort Добре запитання. Я не думаю, що різниця у ефективності foreach+ breakта reset+ keyнасправді є різною . Але перший виглядає досить дивно, тому для стилістичних питань я віддаю перевагу другому.
troelskn

@EmilioGort: Afaik, foreach () копіює масив внутрішньо. Тож ми можемо вважати, що це повільніше. (Було б добре, якби хтось міг це підтвердити)
donquixote

3
@donquixote Я не знаю точно, але припускаючи, що це звичайний масив (а не об'єкт, що реалізує якийсь інтерфейс або Iterator), я досить впевнений, що foreachвін не створює для нього внутрішню копію, а просто ітераціює покажчик , схоже на використання більш низького рівня next, і currentт.д.
troelskn

54

Цікаво, що цикл foreach - це насправді найефективніший спосіб зробити це.

Оскільки ОП спеціально запитала про ефективність, слід зазначити, що всі поточні відповіді насправді набагато менш ефективні, ніж передбачення.

Я зробив орієнтир щодо цього за допомогою php 5.4, і метод скидання / вказівника клавіш (прийнята відповідь), здається, приблизно в 7 разів повільніше, ніж foreach. Інші підходи, що маніпулюють усім масивом (array_keys, array_flip), очевидно, навіть повільніше, ніж це, і стають набагато гіршими при роботі з великим масивом.

Foreach взагалі неефективний, сміливо використовуйте його!

Редагувати 2015-03-03:

Сценарії з еталоном були запитані, у мене немає оригінальних, але натомість зробили кілька нових тестів. Цього разу я знайшов передбачення лише приблизно вдвічі швидше, ніж скидання / клавіша. Я використовував масив зі 100 ключами і пробігав кожен метод мільйон разів, щоб отримати помітну різницю, ось код простого еталону:

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

На моєму php 5.5 це виводить:

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

скинути + ключ http://3v4l.org/b4DrN/perf#tabs
foreach http://3v4l.org/gRoGD/perf#tabs


3
Чи є у вас десь орієнтири. Як і те, як ви протестували і т. Ін., Дякую за те, що запустили їх!
грип

Я хотів би зазначити той факт, що існує весь масив, використаний у всьому тесті. Я думаю, що цей факт суттєво впливає на підхід foreach. Як згадував @donquixote в коментарі до відповіді вище - foreach внутрішньо копіює масив. Я можу уявити, що ця копія повторно використовується під час виконання еталону, оскільки уникнення копіювання масиву підвищує продуктивність лише в рамках цього тесту.
Jarda

2
@Jarda Що стосується php7, foreachніколи не копіюйте масив, якщо ви безпосередньо не модифікуєте його всередині циклу foreach. На php5 структура масиву може бути скопійована в деяких випадках (коли її перерахунок> 1), і ви насправді маєте рацію, це може вплинути на це. На щастя, на php7, де ця проблема була вирішена, не варто хвилюватися. Ось чудовий прочитання як про те, як працює foreach під капотом, так і як він працював у минулому.
Вебмут

2
станом на php7.2, використовуючи вищевказаний показник, передбачення все ще найшвидше
billynoah

36

key($an_array) дасть вам перший ключ

редагувати за Blixt: слід подзвонити reset($array);раніше, key($an_array)щоб скинути вказівник на початок масиву.


7
Пам'ятайте, що вказівник масиву може бути не на першому елементі, дивіться мою відповідь.
Blixt

Я думаю, що ця відповідь допоможе моєму випадку без скидання, оскільки я спершу переконуюсь, що в масиві є лише один елемент. Спасибі
groovenectar


22

На 2018 рік +

Починаючи з PHP 7.3, є array_key_first()функція, яка досягає саме цього:

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

Документація доступна тут . 😉


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

2
Це, мабуть, не найефективніше.
Яда

3
@ Так, але це може бути помітно в рідкісних випадках; у більшості випадків читабельність та ремонтопридатність мають набагато більше значення; а також я віддаю перевагу рішення, яке не мутує оригінальні об'єкти / масиви: наприклад, скидання ($ ar); $ key = ключ ($ ar); - це не завжди гарна ідея, я б скоріше вибрав рішення MartyIX, яке є більш стислим, ніж моє, наприклад: array_keys ($ ar) [0];
Сергій Соколенко

20

Якщо ефективність не для вас важлива, ви можете використовувати array_keys($yourArray)[0]PHP 5.4 (і вище).

Приклади:

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

Перевага перед рішенням:

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

полягає в тому, що ви можете передавати array_keys($arr)[0]як параметр функції (тобто doSomething(array_keys($arr)[0], $otherParameter)).

HTH


3
Чи array_keys($arr)[0]синтаксис дійсний?
trante

5
Це в PHP 5.4. Це називається array dereferencing. Дивіться наприклад: schlueters.de/blog/archives/…
Мартін Всетічка

@trante, Це дійсно будь-якою мовою під сонцем, крім PHP <5.4.
Pacerier


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

1
max()Доза @jurgemaister не повертає перший ключ масиву асоцій . Максимальне повернення максимального значення списку або елементів масиву
Хамідреза

5
Не запит на ОП, але дуже корисний у деяких ситуаціях.
д.раєв

9

Це також може бути рішенням:

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

Я перевірив це, і він працює.

Робочий кодекс .


3
array_flip (): може перевертати лише значення STRING та INTEGER!
Мауро

5

Щоб покращити рішення Webmut , я додав таке рішення:

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

Вихід для мене на 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 

Якщо я роблю це для масиву розміром 10000, то результати стають

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 

Метод array_keys триває час за 30 секунд (маючи лише 1000 елементів, час для решти приблизно такий же, але метод array_keys мав приблизно 7,5 секунд).


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

3

Найкращий спосіб, який працював на мене, був

array_shift(array_keys($array))

array_keys отримує масив ключів з початкового масиву, а потім array_shiftвирізає з нього перше значення елемента. Для цього вам знадобиться PHP 5.4+


3

Це простіший спосіб, який я коли-небудь знаходив. Швидкий і лише два рядки коду :-D

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

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


1
Включення пояснення дійсно допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду
MichaelvE

0

Одноколісний:

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

# echos 'key1'

0

Сьогодні мені довелося шукати перший ключ мого масиву, повернений запитом POST. (І зазначте номер ідентифікатора форми тощо)

Ну, я знайшов це: поверніть перший ключ асоціативного масиву в PHP

http://php.net/key

Я це зробив, і це працює.

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

Можливо, це буде еко-15 хвилин іншого хлопця. CYA.


-2

Ви можете грати зі своїм масивом

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

Для отримання першого елемента масиву ви можете використовувати, currentа для останнього елемента можна використовуватиend

Редагувати

Тільки заради того, що ви не отримаєте більше голосів за відповідь, ви можете перетворити вам ключ на значення array_keysта використовувати, як показано вище.


1
Це значення, а не ключі.
Віктор Шредер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.