การเข้าถึงอาร์เรย์ที่เชื่อมโยงโดยดัชนีจำนวนเต็มใน PHP


93

ฉันต้องการตั้งค่าของอาร์เรย์ที่เชื่อมโยงโดยใช้ดัชนีอาร์เรย์ของคู่คีย์ / ค่า ตัวอย่างเช่น:

$my_arr = array( "bling" => "some bling", "bling2" => "lots O bling" );
$my_arr[1] = "not so much bling";  // Would change the value with key bling2.

จะทำสิ่งนี้ได้อย่างไรโดยไม่ต้องใช้คีย์สตริง

คำตอบ:


189

ใช้array_keys

$keys = array_keys($my_arr);
$my_arr[$keys[1]] = "not so much bling";

หวังว่านี่จะช่วยได้


4
ตามหมายเหตุด้านข้างเหตุใดนักพัฒนา PHP จึงสร้างวิธีการเข้าถึงอาร์เรย์ที่ไม่ใช้งานง่าย
Marty

3
@Marty สิ่งนี้มีส่วนเกี่ยวข้องกับวิธีการใช้งาน PHP devs น้อยลง แต่มีมากกว่านั้นด้วยความเข้าใจผิดของคุณเกี่ยวกับการทำงานของอาร์เรย์ ในทางเทคนิคข้างต้นยังคงใช้ชื่อที่เชื่อมโยงกัน ไม่มีความสัมพันธ์ระหว่างคีย์ดัชนีตัวเลขและการเชื่อมโยง
Gordon

2
คุณสร้างอาร์เรย์เชื่อมโยงเนื่องจากสิ่งที่คุณกำลังมองหามีความสำคัญมากกว่าตำแหน่งในอาร์เรย์ ผมคิดว่านี่เป็นจุดที่ดี สมมติว่าคุณมีอาร์เรย์ที่มีชื่อนักเรียนเป็นคีย์และที่อยู่เป็นค่า คุณสามารถเข้าถึงที่อยู่ของนักเรียนได้โดยใช้ชื่อ ตำแหน่งของอาร์เรย์ไม่เกี่ยวข้อง name of the studentและคุณสามารถเรียงลำดับอาร์เรย์โดย
Donovan

@Gordon ในทางเทคนิคมันเป็นเรื่องจริง แต่โปรแกรมเมอร์กำลังให้ตัวเลขไม่ใช่สตริง ฉันคิดว่านี่คือความหมายของwithout using a key string.
Donovan

2
@ อัลเบิร์ตคุณกำลังแมปหมายเลขนี้กับสตริงคีย์ที่เหมาะสม นั่นไม่ได้หมายความว่าarray[1] === $array['foo']แม้ว่า $array[1]อาร์เรย์อาจจะยังคงมีค่าอีก โปรดทราบว่าฉันไม่ได้บอกว่าวิธีแก้ปัญหาของคุณผิด มันเป็นสมมติฐานของ OP
Gordon

27

ไม่มีความสัมพันธ์ระหว่างคีย์ดัชนีตัวเลขและการเชื่อมโยง

เมื่อคุณบอกว่าคุณต้องการที่จะกำหนดค่าของอาเรย์โดยใช้ดัชนีอาร์เรย์ของคีย์ / ค่าแล้วคุณต้องใช้คีย์ที่กำหนด, การตั้งค่าไม่ได้เช่นเดียวกับการตั้งค่า$array[1]$array['foo']

พิจารณาอาร์เรย์นี้

print_r( array('foo', 'foo' => 'bar', 'baz', 'some' => 'value') );

นี้จะให้

Array
(
    [0] => foo
    [foo] => bar
    [1] => baz
    [some] => value
)

foo เป็นองค์ประกอบที่สองในอาร์เรย์ นั่นคือชดเชยแต่มันมีอะไรจะทำอย่างไรกับดัชนี 1. ในขณะที่คุณสามารถดูในอาร์เรย์ที่ดังกล่าวข้างต้นดัชนี 1 bazมีความเกี่ยวข้องกับ มันผิดที่จะคิดว่าเพียงเพราะfooเป็นคีย์แรกที่เชื่อมโยงมันมีส่วนเกี่ยวข้องกับคีย์ตัวเลขจริง 1 เหมือนกับsomeไม่สัมพันธ์กับ 2

ในทำนองเดียวกันสำหรับอาร์เรย์แบบผสมดังที่แสดงไว้ด้านบนโซลูชันที่array_keysแนะนำที่อื่นในไซต์นี้จะใช้ไม่ได้เนื่องจาก

print_r( array_keys(array('foo', 'foo' => 'bar', 'baz', 'some' => 'value')) );

จะให้

Array
(
    [0] => 0
    [1] => foo
    [2] => 1
    [3] => some
)

ดังนั้นเมื่อคุณทำคุณจะทำจริงๆ$array[$keys[1]] $array['foo']แต่ถ้าคุณต้องการที่จะเข้าถึงค่าเชื่อมโยงสองในอาร์เรย์ที่ ( 'some') คุณไม่สามารถทำ$array[$keys[2]]เพราะที่จะประเมินและว่า$array[1]baz

ออฟเซ็ตขององค์ประกอบไม่เกี่ยวข้องกับคีย์หรือค่าของมัน

print_r(
    array(
        100    => 'foo',
        'foo'  => 'bar',
        50     => 'baz',
        'some' => 'value'
    )
);

หมายความว่าจริงๆ

Array
( //key       value     offset/position
    [100]  => foo       // 0
    [foo]  => bar       // 1
    [50]   => baz       // 2
    [some] => value     // 3
)

ซึ่งหมายความว่าองค์ประกอบที่ offset 0 คือ foo แม้ว่าคีย์จะเป็น 100 ก็ตามหากคุณต้องการแยกองค์ประกอบจากอาร์เรย์ด้วยออฟเซ็ตคุณต้องใช้

$third = array_splice($array, 2, 1);
echo $third[0]; // baz

สิ่งนี้จะสร้างอาร์เรย์ที่มีเฉพาะองค์ประกอบที่ตำแหน่งที่สาม

หรือคุณสามารถใช้ArrayIteratorไฟล์. ArrayIteratorดำเนินSeekableอินเตอร์เฟซที่ช่วยให้คุณขอให้อยู่ในตำแหน่งที่เฉพาะเจาะจง / ชดเชยในอาร์เรย์และจากนั้นเรียกว่า

$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value

nit เล็กน้อย: "ถ้าคุณต้องการเข้าถึงค่า Associative ที่สองในอาร์เรย์นั้น ('some') คุณไม่สามารถทำ $ array [$ keys [2]] ได้เพราะจะประเมินเป็น $ array [1] และนั่นคือ baz" ใน ทางเทคนิคแล้ว นั่นเป็นเพราะทุกคีย์รวมทั้งคนที่เป็นตัวเลขที่มีการเชื่อมโยงกุญแจ - array_keysค่าส่งกลับโดย ไม่มีเอนทิตีเช่น "คีย์ที่ไม่เชื่อมโยง" หากคุณต้องการชี้ให้เห็นว่าคุณไม่สามารถส่งคืนคีย์สตริงที่ 2 ได้(โดยสมมติว่าอาร์เรย์คีย์มีสตริงเท่านั้น) สิ่งที่คุณพูดนั้นถูกต้อง $stringKeys = array_filter(array_keys($array), "is_string");ให้คีย์สตริง
ToolmakerSteve

17

ในขณะที่array_keys()อนุญาตให้เข้าถึงคีย์ที่ n array_valuesจะให้ค่าที่ n แก่คุณ

<?php
$array = [
   0     => 'Zero',
   '1'   => 'One',
   'Two' => 'Two',
];
echo array_values($array)[2];
?>

จะส่งออก 'สอง'

มีข้อได้เปรียบเหนือข้ออื่น ๆ หรือไม่? สิ่งที่รองลงมาเท่านั้นที่ฉันเห็นคือจำนวนการเข้าถึงอาร์เรย์

ด้วยarray_keys()คุณต้อง 3.

  1. รับคีย์จากอาร์เรย์ข้อมูล
  2. รับคีย์ที่ n จากรายการคีย์
  3. รับค่าโดยใช้คีย์ที่ n จากอาร์เรย์ข้อมูล

ด้วยarray_values()คุณต้องการเพียง 2

  1. รับค่าจากอาร์เรย์ข้อมูล
  2. รับค่าที่ n จากรายการค่า

แต่ในทางกลับกันคีย์จะมีขนาดเล็กกว่าปกติและข้อมูลอาจซ้อนกันอย่างมหาศาลดังนั้นการใช้คีย์array_keys()จะปลอดภัยกว่า


3

หากอาร์เรย์มีขนาดใหญ่ทั้งคู่array_keysและarray_valuesจะสิ้นเปลืองเนื่องจากจะจัดสรรอาร์เรย์ใหม่ที่มีขนาดเท่ากับของเดิมเพียงเพื่อให้ได้คีย์ที่n (หรือค่า)

array_sliceยอมรับการชดเชยจำนวนเต็มและทำงานกับอาร์เรย์ที่เชื่อมโยงกัน คุณสามารถใช้เพื่อรับ (และตั้งค่า) คีย์ที่nในเวลาคงที่

// This will at most allocate 2 temporary arrays of 1 element each
$key = array_keys(array_slice($array, $n, 1, true))[0];

$array[$key] = $value;

2
ทางออกที่ดีที่นี่!
Daan

1

ลองทำตามนี้ มันเหมาะสำหรับคุณ

$result= array_values($my_arr); // Array with indexes you need

1
โปรดใช้ความระมัดระวังในการโพสต์ในกระทู้เก่าซึ่งมีการตอบกลับหลายครั้งและมีคำตอบที่ยอมรับ คุณต้องอธิบายว่าเหตุใดคำตอบใหม่ของคุณจึงดีกว่าคำตอบที่มีอยู่
APC

0

ความเป็นไปได้อีกประการหนึ่งคือการแปลงเป็นอาร์เรย์ปกติ:

$ arraybuff = ระเบิด ("~~~", $ my_arr);
$ my_arr = ระเบิด ("~~~", $ arraybuff);

โดยที่ "~~~" คือตัวคั่นที่จะไม่เกิดขึ้นในข้อมูลของคุณ

ตอนนี้คุณสามารถเข้าถึงอาร์เรย์โดยใช้ดัชนีตัวเลขเท่ากับออฟเซ็ต

หากคุณยังต้องการคงอาร์เรย์ที่เชื่อมโยงไว้ให้กำหนดให้กับตัวแปรอื่น


เนื่องจากคุณควรพิจารณาอยู่เสมอตัวคั่นที่แน่นอนนี้สามารถเกิดขึ้นได้ในข้อมูลของคุณแนวคิดนี้ใช้ได้เพียง 99.9999999% มีโซลูชันหลายอย่างที่จะทำงานได้ 100% นอกจากนี้ยังตั้งค่าโปรเซสเซอร์ให้ทำงานได้มากและสิ้นเปลืองหน่วยความจำสำหรับการเข้าถึงอาร์เรย์แบบธรรมดา
user426486
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.