รับคีย์แรกในอาเรย์แบบเชื่อมโยง (อาจ)


756

วิธีที่ดีที่สุดในการกำหนดคีย์แรกในอาเรย์ที่เป็นไปได้คืออะไร ครั้งแรกที่ฉันคิดว่าจะได้รับอาร์เรย์แล้วทำลายมันทันทีเช่นนี้

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

ดังนั้นการมี $ key จะมีคีย์แรก แต่ดูเหมือนจะไม่มีประสิทธิภาพ ไม่มีใครมีทางออกที่ดีกว่า?


4
ทำไมถึงไม่มีประสิทธิภาพในแต่ละครั้ง
Emilio Gort

2
เมื่อเทียบกับคำตอบทั้งหมด foreach ยังคงเป็นFIDDLE ที่เร็วที่สุด, PHP 5.3 , การทดสอบ localhost ของฉันบน PHP 5.5 แสดงให้เห็นว่าความแตกต่างนั้นต่างจาก foreach เล็กน้อย
Danijel

3
@Danijel foreachมีความหมายผิด
Pacerier

2
@AlexS ไม่ว่าจะทำงานeach($arr)['key']หรือไม่each($arr)[0]ก็ตาม
Pacerier

1
@Danijel ไม่มีอีกแล้ว ... สำคัญ: 0.0107, foreach: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 `นั่นยังคงเป็นจริงหรือ? ฉันสับสน
Dmitry Pashkevich

13
@DmitryPashkevich: ไม่ต้องกังวลกับความคิดเห็นนั้น พวกเขาไม่ได้พูดถึงarrayวัตถุ แต่เป็นวัตถุที่กำหนดเอง (นั่นไม่ใช่อาร์เรย์จริง) ฉันเดาว่าพวกเขามีความแตกต่างในโครงสร้างข้อมูลที่สับสน แต่โดยทั่วไปแล้วresetคืนค่าของ "คีย์" ตัวแรกซึ่งสำหรับวัตถุจะเป็น$propตัวอย่างในรายงาน "บั๊ก" แต่สำหรับอาร์เรย์เป็นคีย์แรก ดังนั้นไม่ต้องกังวลตราบใดที่คุณใช้อาร์เรย์จริง (สร้างด้วยarray(…)) คุณจะไม่มีปัญหา
Blixt

2
ควรระบุว่า end () และ reset () มีผลข้างเคียง อย่างไรก็ตามรหัสส่วนใหญ่ในโลกไม่ได้ขึ้นอยู่กับตัวชี้ภายในที่ใดก็ได้ดังนั้นโดยทั่วไปจะไม่มีปัญหา
donquixote

1
@ user3019105 มีเพียงหนึ่งตัวชี้ภายในต่ออาร์เรย์ซึ่งหมายความว่าถ้ารหัสใด ๆ นอกการทำงานของคุณเปลี่ยนแปลง (โดยการเรียกคือnext, reset, endหรือบ่วงผ่านแถว) keyคุณจะไม่ได้รับค่าที่คาดหวังเมื่อคุณเรียก ใช่เสมอโทรresetก่อนใช้keyเพื่อให้แน่ใจว่าคุณได้รับสิ่งที่คุณต้องการ
Blixt

80

array_keysส่งคืนอาร์เรย์ของคีย์ ใช้รายการแรก หรือคุณสามารถโทรในอาร์เรย์และต่อมาreset keyวิธีหลังอาจจะเร็วกว่าเล็กน้อย (ฉันไม่ได้ทดสอบ) แต่มีผลข้างเคียงของการรีเซ็ตตัวชี้ภายใน


52
เพียงแค่ทราบ (ล่าช้า) สำหรับผู้อ่านในอนาคตของเรื่องนี้: แนวทางหลังไม่ใช่แค่ "เร็ว" เร็วกว่าเท่านั้น มีความแตกต่างอย่างมากระหว่างการวนซ้ำทั้งอาร์เรย์เก็บคีย์ทั้งหมดไว้ในอาร์เรย์ที่สร้างขึ้นใหม่และขอคีย์แรกของอาร์เรย์เป็นสตริง
Blixt

3
ทำไม foreach ที่ไม่มีประสิทธิภาพจึงมีคำถามเปรียบเทียบกับคำตอบเหล่านี้ทั้งหมด
Emilio Gort

5
@EmilioGort เป็นคำถามที่ดี ฉันไม่คิดว่าจะมีความแตกต่างในประสิทธิภาพของforeach+ breakและreset+ keyจริง ๆ แต่ก่อนหน้านี้ดูค่อนข้างแปลกดังนั้นสำหรับประเด็นโวหาร
troelskn

@EmilioGort: Afaik, foreach () คัดลอกอาร์เรย์ภายใน ดังนั้นเราสามารถสรุปได้ว่าช้าลง (จะดีถ้ามีคนสามารถยืนยันได้ว่า)
donquixote

3
@donquixote ฉันไม่รู้แน่ชัด แต่สมมติว่าเป็นอาร์เรย์ปกติ (และไม่ใช่วัตถุที่ใช้อินเทอร์เฟซหรือ Iterator บางชนิด) ฉันค่อนข้างแน่ใจforeachว่าไม่ได้สร้างสำเนาภายในสำหรับมัน แต่แทนที่จะทำซ้ำตัวชี้ คล้ายกับการใช้ในระดับต่ำมากขึ้นnext, currentฯลฯ
troelskn

54

ที่น่าสนใจคือการวนรอบ foreach เป็นวิธีที่มีประสิทธิภาพที่สุดในการทำสิ่งนี้

เนื่องจาก OP ได้ถามถึงประสิทธิภาพโดยเฉพาะจึงควรชี้ให้เห็นว่าคำตอบในปัจจุบันทั้งหมดนั้นมีประสิทธิภาพน้อยกว่า foreach มาก

ฉันทำเกณฑ์มาตรฐานนี้ด้วย php 5.4 และวิธีการรีเซ็ต / คีย์ตัวชี้ (คำตอบที่ยอมรับได้) ดูเหมือนว่าจะช้ากว่า foreach ประมาณ 7 เท่า วิธีอื่น ๆ ในการจัดการกับอาเรย์ทั้งหมด (array_keys, array_flip) เห็นได้ชัดว่าช้าลงกว่านั้นและแย่ลงมากเมื่อทำงานกับอาเรย์ขนาดใหญ่

Foreach นั้นไม่มีประสิทธิภาพเลยรู้สึกอิสระที่จะใช้มัน!

แก้ไข 2015-03-03:

มีการร้องขอสคริปต์การวัดประสิทธิภาพฉันไม่มีแบบดั้งเดิม แต่ได้ทำการทดสอบใหม่แทน เวลานี้ฉันพบ foreach เพียงสองครั้งเร็วพอรีเซ็ต / คีย์ ฉันใช้อาร์เรย์ 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
คุณมีมาตรฐานบ้างไหม เช่นเดียวกับที่คุณทดสอบ ฯลฯ ขอบคุณสำหรับการใช้งาน!
ไข้หวัดใหญ่

ฉันต้องการจะชี้ให้เห็นถึงความจริงว่ามีอาร์เรย์เดียวกันที่ใช้ผ่านการทดสอบทั้งหมด ฉันคิดว่าความจริงข้อนี้มีอิทธิพลต่อวิธีการต่าง ๆ อย่างมีนัยสำคัญ ดังที่ @donquixote พูดถึงในความคิดเห็นต่อการตอบกลับข้างต้น - foreach คัดลอกอาร์เรย์ภายใน ฉันสามารถจินตนาการได้ว่าสำเนานี้สามารถนำไปใช้ใหม่ได้ในขณะที่รันเกณฑ์มาตรฐานเนื่องจากการหลีกเลี่ยงการคัดลอกอาเรย์จะช่วยเพิ่มประสิทธิภาพในการทดสอบนี้เท่านั้น
Jarda

2
@ Jarda ในฐานะของ php7 ห้ามforeachคัดลอกอาร์เรย์เว้นแต่ว่าคุณจะแก้ไขโดยตรงภายในวงวน foreach ใน php5 โครงสร้างอาเรย์สามารถคัดลอกได้ในบางกรณี (เมื่อ refcount ของมัน> 1) และคุณพูดถูกมันอาจมีอิทธิพลสำคัญ โชคดีที่ไม่มีอะไรต้องกังวลเกี่ยวกับ php7 ซึ่งปัญหานี้ได้รับการแก้ไข นี่คือการอ่านที่ยอดเยี่ยมทั้งเกี่ยวกับวิธีการทำงานต่าง ๆ ภายใต้ประทุนในขณะนี้และวิธีการทำงานในอดีต
Webmut

2
ในฐานะของ php7.2 โดยใช้เกณฑ์มาตรฐานข้างต้น foreach ยังคงเร็วที่สุด
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
นี่อาจไม่ได้มีประสิทธิภาพมากที่สุด
Yada

3
@Yada ใช่ แต่อาจสังเกตได้ในบางกรณี ในกรณีส่วนใหญ่การอ่านและการบำรุงรักษามีความสำคัญมากขึ้น และฉันยังชอบวิธีแก้ปัญหาที่ไม่ได้กลายพันธุ์วัตถุ / อาร์เรย์เดิมเช่นรีเซ็ต ($ ar); $ key = key ($ ar); - ไม่ใช่ความคิดที่ดีเสมอไปฉันควรเลือกโซลูชันของ MartyIX ที่กระชับกว่าของฉันเช่น: array_keys ($ ar) [0];
Sergiy Sokolenko

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/…
Martin Vseticka

@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
@jurgemaister max()dose ไม่ส่งคืนคีย์แรกของอาร์เรย์ assoc ส่งคืนค่าสูงสุดของรายการหรือรายการอาร์เรย์
Hamidreza

5
ไม่ใช่คำขอ OP แต่มีประโยชน์มากในบางสถานการณ์
d.raev

9

นี่อาจเป็นวิธีแก้ปัญหา:

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

ฉันได้ทำการทดสอบแล้วและใช้งานได้

รหัสการทำงาน


3
array_flip (): สามารถพลิกค่า STRING และ INTEGER ได้เท่านั้น!
Mauro

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 

ถ้าฉันทำเช่นนี้สำหรับอาร์เรย์ขนาด 10,000 ผลลัพธ์ก็จะกลายเป็น

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 วินาที (มีเพียง 1,000 องค์ประกอบเวลาสำหรับส่วนที่เหลือเป็นเรื่องเดียวกัน แต่วิธีการ array_keys มีประมาณ 7.5 วินาที)



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

วันนี้ฉันต้องค้นหาคีย์แรกของอาร์เรย์ที่ส่งคืนโดยคำขอ POST (และบันทึกหมายเลขสำหรับแบบฟอร์ม id ฯลฯ )

ฉันได้พบสิ่งนี้แล้ว: ส่งคืนคีย์แรกของอาร์เรย์ที่เชื่อมโยงใน 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
นี่คือค่าไม่ใช่กุญแจ
Victor Schröder
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.