คุณจะลบองค์ประกอบอาร์เรย์ใน foreach loop ได้อย่างไร?


127

ฉันต้องการวนรอบอาร์เรย์ด้วยforeachเพื่อตรวจสอบว่ามีค่าอยู่หรือไม่ หากมีค่าอยู่ฉันต้องการลบองค์ประกอบที่มีอยู่

ฉันมีรหัสต่อไปนี้:

foreach($display_related_tags as $tag_name) {
    if($tag_name == $found_tag['name']) {
        // Delete element
    }
}

ฉันไม่รู้วิธีลบองค์ประกอบเมื่อพบค่าแล้ว ฉันจะลบมันได้อย่างไร?

ฉันต้องใช้foreachสำหรับปัญหานี้ อาจมีทางเลือกอื่นให้foreachและคุณสามารถแบ่งปันได้

คำตอบ:


220

หากคุณได้รับคีย์คุณสามารถลบรายการนั้นได้ดังนี้:

foreach ($display_related_tags as $key => $tag_name) {
    if($tag_name == $found_tag['name']) {
        unset($display_related_tags[$key]);
    }
}

3
ข้อมูลเพิ่มเติมบางอย่างเกี่ยวกับการเพิ่มประสิทธิภาพโดยใช้$key => &$tag_name stackoverflow.com/a/2008893/922522
Justin

5
โปรดทราบว่าอาร์เรย์ที่จัดทำดัชนีซึ่งมีรายการที่ไม่ได้ตั้งค่าอาจแสดงเป็นวัตถุแทนอาร์เรย์หลังจาก a json_encode(). คุณสามารถแก้ปัญหานี้ได้ด้วย$display_related_tags = array_values ($display_related_tags);การforeachวนซ้ำ
MártonTamás

โปรดทราบว่าเคล็ดลับที่นี่คือการเพิ่มมูลค่าให้กับ foreach loop ;-)
Mr Washington

5
โปรดดูคำตอบของ @Neils คุณจะพบข้อบกพร่องที่ไม่คาดคิดโดยเฉพาะอย่างยิ่งหากคุณทำงานกับ Array ของ stdClasses คุณชอบพฤติกรรมที่ไม่คาดคิดหรือไม่? ฉันไม่.
happy_marmoset

@happy_marmoset คำตอบของ Neils ไม่ได้ช่วยอะไร Snippet $projects = array_filter($projects, function ($project) { return count($project->roles) > 0; });จะแปลงผลลัพธ์เป็นวัตถุ
Paritosh

36

ทางออกที่ดีกว่าคือการใช้array_filterฟังก์ชัน:

$display_related_tags =
    array_filter($display_related_tags, function($e) use($found_tag){
        return $e != $found_tag['name'];
    });

ตามที่เอกสาร php อ่าน:

เนื่องจาก foreach อาศัยตัวชี้อาร์เรย์ภายในใน PHP 5 การเปลี่ยนแปลงภายในลูปอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด

ใน PHP 7 foreach ไม่ใช้ตัวชี้อาร์เรย์ภายใน


โปรดทราบว่าพารามิเตอร์ที่ 3 ควรเป็น ARRAY_FILTER_USE_KEY เพื่อส่งผ่านคีย์เป็น $ e ที่นี่
namezero

@namezero ตกลงทำไมถึงสำคัญที่นี่?
AbraCadaver

@AbraCadaver จากเอกสาร ( php.net/manual/en/function.array-filter.php ): ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value ARRAY_FILTER_USE_BOTH - pass both value and key as arguments to callback instead of the value Default is 0 which will pass value as the only argument to callback instead. ที่กล่าวว่าอ่านคำตอบอีกครั้งในกรณีนี้แน่นอนว่ามันจะไม่สำคัญอย่างที่คุณอ้าง
namezero

สำคัญหากคุณสนใจที่จะเก็บอาร์เรย์ให้เป็นอาร์เรย์ที่เรียงลำดับคุณต้องเรียกใช้display_related_tags = array_values(display_related_tags);หลังจากนั้น
guyaloni

9
foreach($display_related_tags as $key => $tag_name)
{
    if($tag_name == $found_tag['name'])
        unset($display_related_tags[$key];
}

3
'ยกเลิกการลิงก์' ยกเลิกการลิงก์ไฟล์ไม่มีส่วนเกี่ยวข้องกับตัวแปรหรือโดยเฉพาะอย่างยิ่งอาร์เรย์ บางทีคุณอาจหมายถึง 'unset'?
AMN

6

แทนที่จะทำ foreach () loop บนอาร์เรย์การใช้ array_search () จะเร็วกว่าเพื่อค้นหาคีย์ที่เหมาะสม ในอาร์เรย์ขนาดเล็กฉันจะใช้ foreach เพื่อการอ่านที่ดีขึ้น แต่สำหรับอาร์เรย์ที่ใหญ่กว่าหรือมักเรียกใช้โค้ดสิ่งนี้ควรจะเหมาะสมกว่าเล็กน้อย:

$result=array_search($unwantedValue,$array,true);
if($result !== false) {
  unset($array[$result]);   
}

จำเป็นต้องใช้ตัวดำเนินการเปรียบเทียบที่เข้มงวด! == เนื่องจาก array_search () สามารถคืนค่า 0 เป็นดัชนีของ $ unantedValue

นอกจากนี้ตัวอย่างข้างต้นจะลบเพียงค่าแรก $ unantedValue หาก $ unantedValue สามารถเกิดขึ้นได้มากกว่าหนึ่งครั้งใน $ array คุณควรใช้ array_keys () เพื่อค้นหาทั้งหมด:

$result=array_keys($array,$unwantedValue,true)
foreach($result as $key) {
  unset($array[$key]);
}

ตรวจสอบhttp://php.net/manual/en/function.array-search.phpสำหรับข้อมูลเพิ่มเติม


0

หากคุณมีสถานการณ์ที่คุณต้องลบมากกว่าหนึ่งค่าจากอาร์เรย์ foreach ในกรณีนี้คุณต้องส่งผ่านค่าโดยการอ้างอิงสำหรับแต่ละค่า: ฉันพยายามอธิบายสถานการณ์นี้:

foreach ($manSkuQty as $man_sku => &$man_qty) {

               foreach ($manufacturerSkus as $key1 => $val1) {

  // some processing here and unset first loops entries                     
 //  here dont include again for next iterations
                           if(some condition)
                            unset($manSkuQty[$key1]);

                        }
               }
}

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


0

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

public static function removeKeysFromAssociativeArray($associativeArray, $keysToUnset)
{
    if (empty($associativeArray) || empty($keysToUnset))
        return array();

    foreach ($associativeArray as $key => $arr) {
        if (!is_array($arr)) {
            continue;
        }

        foreach ($keysToUnset as $keyToUnset) {
            if (array_key_exists($keyToUnset, $arr)) {
                unset($arr[$keyToUnset]);
            }
        }
        $associativeArray[$key] = $arr;
    }
    return $associativeArray;
}

โทรไลค์:

removeKeysFromAssociativeArray($arrValues, $keysToRemove);

-1

ดังที่ได้กล่าวไปแล้วคุณต้องการทำการ foreach ด้วยคีย์และยกเลิกการตั้งค่าโดยใช้คีย์ - แต่โปรดทราบว่าการกลายพันธุ์อาร์เรย์ระหว่างการทำซ้ำเป็นความคิดที่ไม่ดีโดยทั่วไปแม้ว่าฉันจะไม่แน่ใจเกี่ยวกับกฎของ PHP ในเรื่องนี้ เฉพาะหน้า


2
php foreach จะดำเนินการกับอาร์เรย์ทั้งหมดโดยไม่คำนึงถึง ทดสอบการยกเลิกการตั้งค่าที่อยู่ถัดไปในการทำซ้ำ มันจะวนซ้ำตามค่าชดเชย แต่ค่าจะเป็นโมฆะ
Kevin Peno

หากคุณไม่กลายพันธุ์อาร์เรย์ในระหว่างการทำซ้ำแล้วจะกลายพันธุ์อาร์เรย์ได้อย่างไร? อาจเป็นค่าเฉลี่ยforeachหรือforโครงสร้างแทนการทำซ้ำโดยทั่วไป?
Gherman

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