การลบรายการอาร์เรย์ตามค่า


166

ฉันต้องการลบรายการอาร์เรย์ด้วยค่าที่กำหนด:

if (in_array($id, $items)) {
    $items = array_flip($items);
    unset($items[ $id ]);
    $items = array_flip($items);
}

มันสามารถทำได้ในทางที่สั้นกว่า (มีประสิทธิภาพมากขึ้น)?


คำตอบ:


423

มันสามารถทำได้ด้วยง่ายหนึ่งซับ

มีอาร์เรย์นี้:

$arr = array('nice_item', 'remove_me', 'another_liked_item', 'remove_me_also');

คุณทำได้:

$arr = array_diff($arr, array('remove_me', 'remove_me_also'));

และมูลค่าของ$arrจะเป็น:

array('nice_item', 'another_liked_item')

หวังว่าจะช่วยเขียนโค้ดที่สวยงาม


2
ไม่มีก็ไม่ทำงานร่วมกับอาร์เรย์อ้างอิงที่array_diffฟังก์ชั่นที่ไม่ทำลายก็จะส่งกลับอาร์เรย์ใหม่
Alejandro García Iglesias

2
@ srcspider ทำไมไม่ $referenced = array_diff($referenced, $items_to_remove);
Alejandro García Iglesias

1
$ referenced ขณะนี้ชี้ไปที่อาร์เรย์ใหม่อาร์เรย์ที่คุณต้องการเปลี่ยนยังคงมีค่าเก่าอยู่
srcspider

2
@srcspider ดีคุณบอกฉันว่าเกิดอะไรขึ้นที่นี่แล้ว ... codepad.org/11ZhiFP0
Alejandro García Iglesias

1
ความผิดฉันเอง; กลไกการใช้นามแฝงแบบแปรผันของ php จะ
นำพา

37

ฉันกำลังเพิ่มคำตอบที่สอง ฉันเขียนสคริปต์การเปรียบเทียบอย่างรวดเร็วเพื่อลองวิธีการต่างๆที่นี่

$arr = array(0 => 123456);
for($i = 1; $i < 500000; $i++) {
    $arr[$i] = rand(0,PHP_INT_MAX);
}

shuffle($arr);
$arr2 = $arr;
$arr3 = $arr;

/** 
 * Method 1 - array_search()
 */
$start = microtime(true);
while(($key = array_search(123456,$arr)) !== false) {
    unset($arr[$key]);
}
echo count($arr). ' left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 2 - basic loop
 */
$start = microtime(true);
foreach($arr2 as $k => $v) {
    if ($v == 123456) {
        unset($arr2[$k]);
    }
}
echo count($arr2). 'left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 3 - array_keys() with search parameter
 */
$start = microtime(true);
$keys = array_keys($arr3,123456);
foreach($keys as $k) {
    unset($arr3[$k]);
}
echo count($arr3). 'left, in '.(microtime(true) - $start).' seconds<BR>';

วิธีที่สามซึ่งarray_keys()ระบุพารามิเตอร์การค้นหาทางเลือกนั้นน่าจะเป็นวิธีที่ดีที่สุด ตัวอย่างผลลัพธ์:

499999 left, in 0.090957164764404 seconds
499999left, in 0.43156313896179 seconds
499999left, in 0.028877019882202 seconds

ตัดสินโดยวิธีแก้ปัญหาที่ฉันจะใช้แล้วจะเป็น:

$keysToRemove = array_keys($items,$id);
foreach($keysToRemove as $k) {
    unset($items[$k]);
}

ฉันคิดว่า array_search เป็นโค้ดที่อ่านได้มากกว่าการใช้วิธี array_diff Upvote
kendepelchin

@ombat ฉันสงสัยว่าคำสั่งซื้อเกี่ยวข้องกับผลลัพธ์หรือไม่ มีความเป็นไปได้ที่การสับเปลี่ยนจะใส่ค่าที่เรากำลังค้นหาใกล้กับด้านหน้าหรือท้าย นอกเหนือจากนั้น ... +1
ทั่วไปใจแคบ

31

เกี่ยวกับ:

if (($key = array_search($id, $items)) !== false) unset($items[$key]);

หรือหลายค่า:

while(($key = array_search($id, $items)) !== false) {
    unset($items[$key]);
}

array_flip()นี้จะป้องกันการสูญเสียที่สำคัญเช่นกันซึ่งเป็นผลข้างเคียงของ


1
จะไม่ทำงานถ้า $ id เป็นองค์ประกอบอาร์เรย์แรกดีกว่าด้วยวิธีนี้: ถ้า (($ key = array_search ($ id, $ items))! == false) unset ($ items [$ key]);
Marek


8

โซลูชันที่ทรงพลังที่สุดจะใช้array_filterงานซึ่งช่วยให้คุณสามารถกำหนดฟังก์ชั่นการกรองของคุณเอง

แต่บางคนอาจบอกว่ามันค่อนข้างแพงไปหน่อยในสถานการณ์ของคุณ ...
การforeachวนรอบอย่างง่ายเพื่อไปยังแถวลำดับและเอารายการที่คุณไม่ต้องการนั้นควรจะเพียงพอ

ในกรณีของคุณบางสิ่งเช่นนี้ควรทำเคล็ดลับ:

foreach ($items as $key => $value) {
    if ($value == $id) {
        unset($items[$key]);
        // If you know you only have one line to remove, you can decomment the next line, to stop looping
        //break;
    }
}

6

ลองarray_search ()


3
ฉันเพิ่งอ่านเอกสารและแนะนำให้ใช้ array_keys () เพื่อค้นหาคีย์ทั้งหมดที่เกี่ยวข้องกับค่า
Savageman

@Savageman - เห็นด้วย ฉันวิ่งเกณฑ์มาตรฐานอย่างรวดเร็วและarray_keys()ดูเหมือนว่าจะทำงานได้ดีกว่าarray_search()สำหรับงานนี้
zombat

6

โซลูชันของคุณจะทำงานหากคุณมีค่าที่ไม่ซ้ำกันในอาร์เรย์

ดู:

<?php
$trans = array("a" => 1, "b" => 1, "c" => 2);
$trans = array_flip($trans);
print_r($trans);
?>

วิธีที่ดีกว่าจะถูกยกเลิกการตั้งค่าด้วยarray_searchในลูปถ้าจำเป็น


คุณมีสิทธิ แต่ในกรณีนี้โดยเฉพาะอย่างยิ่งผมค่อนข้างมั่นใจว่าค่าจะไม่ซ้ำกัน :)
มาเร็ค



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