PHP array ลบตามค่า (ไม่สำคัญ)


886

ฉันมีอาร์เรย์ PHP ดังนี้

$messages = [312, 401, 1599, 3, ...];

ฉันต้องการลบองค์ประกอบที่มีค่า$del_val(ตัวอย่างเช่น$del_val=401) แต่ฉันไม่รู้รหัสของมัน ความช่วยเหลือนี้อาจ: แต่ละค่าเท่านั้นที่สามารถจะมีครั้งเดียว

ฉันกำลังมองหาฟังก์ชั่นที่ง่ายที่สุดในการทำงานนี้โปรด


1
@ Adam Strudwick แต่ถ้าคุณมีการลบจำนวนมากในอาเรย์นี้มันจะดีกว่าไหมที่จะย้ำมันอีกครั้งและทำให้มันเหมือนกันกับค่า?
dzona

คำถามเดียวกัน: stackoverflow.com/questions/1883421/…
Eric Lavoie

คำตอบ:


1566

ใช้array_search()และunsetลองทำสิ่งต่อไปนี้:

if (($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
}

array_search()ผลตอบแทนที่สำคัญขององค์ประกอบที่พบซึ่งสามารถใช้ในการลบองค์ประกอบที่จาก array unset()เดิมโดยใช้ มันจะกลับมาFALSEเมื่อล้มเหลวอย่างไรก็ตามมันสามารถคืนค่า false-y ในความสำเร็จ (คีย์ของคุณอาจเป็น0ตัวอย่าง) ซึ่งเป็นเหตุผลที่การเปรียบเทียบที่เข้มงวด!==ตัวดำเนิน

if()คำสั่งจะตรวจสอบว่าarray_search()กลับมีค่าและจะดำเนินการถ้ามันไม่ได้


14
$ messages = array_diff ($ messages, array ($ del_val)) จะทำงานด้วยหรือไม่ ประสิทธิภาพที่ดีขึ้นหรือไม่
Adam Strudwick

9
@ อดัมทำไมไม่ลองทดสอบดูล่ะ? ความรู้สึกของฉันอยู่ที่array_diff()จะช้ากว่าที่มันเปรียบเทียบสองอาร์เรย์ไม่เพียงการค้นหาผ่านทางหนึ่งarray_search()เช่น
Bojangles

22
แม้ว่าสิ่งนี้จะถูกต้องคุณควรหลีกเลี่ยงการกำหนดค่าในข้อความสั่งเช่นนั้น มันจะทำให้คุณเดือดร้อน
adlawson

17
เกิดอะไรขึ้นถ้า$keyเป็น0?
evan

16
หากค่าที่คุณค้นหามีคีย์0หรือค่าความผิดพลาดอื่น ๆ มันจะไม่ล้างค่าและรหัสของคุณจะไม่ทำงาน $key === falseคุณควรทดสอบ (แก้ไข - คุณได้รับ)
evan

673

การลบองค์ประกอบออกจากอาร์เรย์นั้นเป็นเพียงแค่การตั้งค่าความแตกต่างกับองค์ประกอบหนึ่ง

array_diff( [312, 401, 15, 401, 3], [401] ) // removing 401 returns [312, 15, 3]

มันสรุปได้เป็นอย่างดีคุณสามารถลบองค์ประกอบได้มากเท่าที่คุณต้องการในเวลาเดียวกันถ้าคุณต้องการ

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


32
ใช้งานได้เฉพาะกับวัตถุที่สามารถแปลงเป็นสตริงได้
nischayn22

7
ฉันดูเหมือนจะได้รับ 'ข้อผิดพลาดในการแยกวิเคราะห์' สำหรับการพูด[$element]ฉันใช้array($element)แทน ไม่มีปัญหา แต่ทุกคนเพียงแค่ต้องการคนที่มีปัญหาที่คล้ายกันที่จะรู้ว่าพวกเขาไม่ได้อยู่คนเดียว
Angad

8
แน่นอนว่าฉันคิดว่า PHP 5.4 ตอนนี้ส่วนใหญ่จะปล่อยสัญกรณ์เก่า ขอบคุณสำหรับคำพูด
Rok Kralj

22
เป็นที่น่าสังเกตว่าด้วยเหตุผลบางอย่างarray_diffใช้(string) $elem1 === (string) $elem2เป็นเงื่อนไขความเท่าเทียมไม่ใช่$elem1 === $elem2อย่างที่คุณคาดหวัง ปัญหาที่ชี้ให้เห็นโดย @ nischayn22 เป็นผลมาจากสิ่งนี้ หากคุณต้องการบางสิ่งบางอย่างเพื่อใช้เป็นฟังก์ชันยูทิลิตี้ที่จะทำงานให้กับอาร์เรย์ขององค์ประกอบที่กำหนดเอง (ซึ่งอาจเป็นวัตถุ) คำตอบของ Bojangle อาจดีกว่าด้วยเหตุผลนี้
Mark Amery

4
นอกจากนี้โปรดทราบว่าวิธีการนี้จะดำเนินการจัดเรียงภายในสำหรับแต่ละอาร์กิวเมนต์array_diff()และทำให้เกิดการรันไทม์สูงสุดถึง O (n lg n) จาก O (n)
แจ็ค

115

วิธีหนึ่งที่น่าสนใจคือการใช้array_keys():

foreach (array_keys($messages, 401, true) as $key) {
    unset($messages[$key]);
}

array_keys()ฟังก์ชั่นใช้เวลาสองพารามิเตอร์เพิ่มเติมเพื่อกลับปุ่มเฉพาะสำหรับค่าเฉพาะและไม่ว่าการตรวจสอบอย่างเข้มงวดเป็นสิ่งจำเป็น (เช่นใช้ === สำหรับการเปรียบเทียบ)

นอกจากนี้ยังสามารถลบรายการอาร์เรย์หลายรายการที่มีค่าเดียวกัน (เช่น[1, 2, 3, 3, 4])


3
@ blasteralfredΨการค้นหาเชิงเส้นคือ O (n); ฉันไม่แน่ใจว่าทำไมคุณถึงคิดว่าเป็นปัญหา
Ja͢ck

1
ใช่มันมีประสิทธิภาพสำหรับการเลือกหลายรายการ / คีย์
Oki Erie Rinaldi

3
นี่คือวิธีที่ดีที่สุดสำหรับอาร์เรย์ที่อาจไม่มีค่าที่ไม่ซ้ำกันทั้งหมด
Derokorian

ปัญหาคือว่ามันออกจากดัชนีของคีย์ onsorted: [0] - a, [2] - b (the [1] หายไป แต่อาร์เรย์ยังคงพลาด)
Rodniko

3
@Rodniko ซึ่งในกรณีนี้คุณจะต้องarray_values()เช่นกัน; แม้ว่าคีย์ที่เหลือจะยังคงอยู่ในลำดับเดียวกันดังนั้นในทางเทคนิคแล้วมันไม่ใช่ "ไม่ได้เรียง"
Ja --ck

55

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

$key = array_search($del_val, $array);
if (false !== $key) {
    unset($array[$key]);
}

อย่างไรก็ตามหากค่าของคุณอาจเกิดขึ้นมากกว่าหนึ่งครั้งในอาเรย์ของคุณคุณสามารถทำได้

$array = array_filter($array, function($e) use ($del_val) {
    return ($e !== $del_val);
});

หมายเหตุ:ตัวเลือกที่สองใช้ได้กับ PHP5.3 + กับClosures เท่านั้น


41
$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);

11
ใช้งานได้เฉพาะเมื่ออาร์เรย์ของคุณไม่มีค่าซ้ำกันนอกเหนือจากค่าที่คุณพยายามลบ
jberculo

2
@jberculo และบางครั้งสิ่งที่คุณต้องการในบางกรณีมันช่วยให้ฉันทำอาร์เรย์ที่ไม่ซ้ำกันกับมันเช่นกัน
DarkMukke

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

ข้อความระบุ "แต่ละค่าสามารถมีได้เพียงครั้งเดียว" สิ่งนี้ควรใช้งานได้ มันคงจะดีถ้าผู้โพสต์ใช้ชื่อตัวแปร smae และเพิ่มคำอธิบายเล็ก ๆ น้อย ๆ
Raatje

2
เห็นได้ชัดว่านี่เร็วที่สุดเมื่อเทียบกับโซลูชันที่เลือกฉันทำการเปรียบเทียบขนาดเล็ก
AMB

28

ดูรหัสต่อไปนี้:

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

คุณทำได้:

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

และนั่นจะทำให้คุณได้รับอาร์เรย์นี้:

array('nice_item', 'another_liked_item')

1
สำหรับอาร์เรย์ที่เชื่อมโยงคุณต้องใช้ array_diff_assoc ()
theCodeMachine

5
สิ่งนี้แตกต่างจากคำตอบนี้อย่างไร
random_user_name

26

วิธีที่ดีที่สุดคือ array_splice

array_splice($array, array_search(58, $array ), 1);

เหตุผลที่ดีที่สุดอยู่ที่นี่ที่http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/


4
นี้จะไม่ทำงานใน arrays [1, 2, 4 => 3]สมาคมและอาร์เรย์ที่มีช่องว่างในคีย์ของพวกเขาเช่น
แจ็ค

ไม่เสียใจที่จะใช้งานได้ โปรดอ่านบทความที่ฉันให้ลิงค์
Airy

4
มันจะไม่ พิจารณาความคิดเห็นข้างบนของฉัน หลังจากที่ผมใช้รหัสของคุณเพื่อลบค่า3อาร์เรย์จะ[1, 2, 3]; กล่าวอีกนัยหนึ่งค่าไม่ได้ถูกลบออก เพื่อความชัดเจนฉันไม่ได้บอกว่ามันล้มเหลวในทุกสถานการณ์เพียงอันนี้
แจ็ค

1
array_splice เป็นวิธีที่ดีที่สุดการยกเลิกการตั้งค่าจะไม่ปรับดัชนีอาเรย์หลังจากการลบ
Raaghu

21

หรือเพียงวิธีการด้วยตนเอง:

foreach ($array as $key => $value){
    if ($value == $target_value) {
        unset($array[$key]);
    }
}

นี่คือที่ปลอดภัยที่สุดของพวกเขาเพราะคุณมีการควบคุมเต็มรูปแบบในอาร์เรย์ของคุณ


1
การใช้array_splice()แทนunset()จะเรียงลำดับดัชนีอาร์เรย์ใหม่ด้วยซึ่งอาจดีกว่าในกรณีนี้
Daniele Orlando

20

ด้วยรหัสต่อไปนี้ค่าซ้ำ ๆ จะถูกลบออกจากข้อความ $

$messages = array_diff($messages, array(401));


3
Up-ได้รับการโหวต มันมีอยู่แล้วในคำตอบอื่น ๆ แต่คุณบอกว่าดีที่สุดโดยทำให้มันง่ายอย่างที่คุณมี คำตอบก็คือ "array_diff"
ghbarratt

1
ดูเรียบง่าย แต่เปลี่ยนความซับซ้อนจาก O (n) เป็น O (n lg n) ในความเป็นจริงมันซับซ้อนกว่ามาก;)
Krzysztof Przygoda

20

หากคุณมี PHP 5.3+จะมีรหัสบรรทัดเดียว:

$array = array_filter($array, function ($i) use ($value) { return $i !== $value; }); 

คุณแน่ใจไหม? การปิดนั้นไม่สามารถเข้าถึงได้$valueดังนั้นจึงต้องใส่ในมินิคลาสเพื่อให้คุณสามารถเข้าถึงได้$valueภายในการปิด ....
random_user_name

@cale_b ฉันได้อัปเดตตัวอย่างแล้ว นอกจากนี้ยังเป็นการอ้างอิง: php.net/manual/en/functions.anonymous.php
David Lin

3
คุณอาจเขียน codebase ทั้งหมดของคุณในบรรทัดเดียวถ้าคุณเรียกว่า "รหัสบรรทัดเดียว"
Milan Simek

16
function array_remove_by_value($array, $value)
{
    return array_values(array_diff($array, array($value)));
}

$array = array(312, 401, 1599, 3);

$newarray = array_remove_by_value($array, 401);

print_r($newarray);

เอาท์พุต

Array ( [0] => 312 [1] => 1599 [2] => 3 )


2
ฉันไม่แน่ใจว่านี่เร็วขึ้นหรือไม่เพราะวิธีนี้เกี่ยวข้องกับการเรียกใช้ฟังก์ชันหลายครั้ง
Julian Paolo Dayag

13

คุณทำได้:

unset($messages[array_flip($messages)['401']]);

คำอธิบาย : ลบองค์ประกอบที่มีคีย์401หลังจากพลิกอาร์เรย์


คุณต้องระวังให้มากหากคุณต้องการรักษาสถานะไว้ เพราะรหัสในอนาคตทั้งหมดจะต้องมีค่าแทนกุญแจ
saadlulu

1
@saadlulu $ messages array จะไม่ถูกพลิกเนื่องจาก array_flip () ไม่มีผลกับ array เดิมดังนั้น array ผลลัพธ์หลังจากใช้บรรทัดก่อนหน้าจะเหมือนกันยกเว้นว่าผลลัพธ์ที่ไม่ต้องการจะถูกลบ
Qurashi

2
ไม่แน่ใจว่านี้ถูกต้องสิ่งที่ถ้ามีหลายองค์ประกอบที่มีค่าของ401?
Zippp

สิ่งนี้จะยังคงรักษาคีย์
Szabolcs Páll


6

ยืมตรรกะของขีดล่าง JS _.reject และสร้างสองฟังก์ชั่น (คนชอบฟังก์ชั่น !!)

array_reject_value:ฟังก์ชั่นนี้เป็นเพียงการปฏิเสธค่าที่ระบุ (ใช้งานได้กับ PHP4,5,7)

function array_reject_value(array &$arrayToFilter, $deleteValue) {
    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if ($value !== $deleteValue) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

array_reject:ฟังก์ชั่นนี้เป็นเพียงการปฏิเสธวิธีการโทร (ทำงานได้กับ PHP> = 5.3)

function array_reject(array &$arrayToFilter, callable $rejectCallback) {

    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if (!$rejectCallback($value, $key)) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

ดังนั้นในตัวอย่างปัจจุบันของเราเราสามารถใช้ฟังก์ชั่นด้านบนดังนี้:

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject_value($messages, 401);

หรือดียิ่งขึ้น: (เพราะนี่จะทำให้เรามีไวยากรณ์ที่ดีกว่าในการใช้เช่นarray_filterหนึ่ง)

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject($messages, function ($value) {
    return $value === 401;
});

ด้านบนสามารถใช้สำหรับสิ่งที่ซับซ้อนมากขึ้นเช่นสมมติว่าเราต้องการลบค่าทั้งหมดที่มากกว่าหรือเท่ากับ 401 เราสามารถทำได้ดังนี้:

$messages = [312, 401, 1599, 3, 6];
$greaterOrEqualThan = 401;
$messages = array_reject($messages, function ($value) use $greaterOrEqualThan {
    return $value >= $greaterOrEqualThan;
});

1
นี่เป็นตัวกรองที่สร้างใหม่ไม่ใช่หรือ php.net/manual/en/function.array-filter.php
Richard Duerr

ใช่แน่นอน. ในขณะที่ฉันกำลังพูดที่โพสต์ "หรือดีกว่า: (เช่นนี้ทำให้เรามีไวยากรณ์ที่ดีกว่าที่จะใช้เช่น array_filter หนึ่ง)" บางครั้งคุณจำเป็นต้องให้ฟังก์ชั่นถูกปฏิเสธเป็นขีดเส้นใต้และมันก็เป็นตรงกันข้ามกับตัวกรอง (และคุณจำเป็นต้องได้รับโค้ดที่น้อยที่สุดเท่าที่จะทำได้) นี่คือสิ่งที่ทำหน้าที่ นี่เป็นวิธีที่ง่ายในการปฏิเสธค่า
John Skoumbourdis

6
$array = array("apple", "banana",'mango');
$array = array_filter($array, function($v) { return $v != "apple"; });

ลองใช้วิธีนี้เป็นวิธีที่ดีที่สุดและเร็วที่สุดในการลบองค์ประกอบตามค่า


5

@Bojangles คำตอบไม่ช่วยฉัน ขอบคุณ.

ในกรณีของฉันอาร์เรย์อาจเชื่อมโยงได้หรือไม่ดังนั้นฉันจึงเพิ่มฟังก์ชันต่อไปนี้

function test($value, $tab) {

 if(($key = array_search($value, $tab)) !== false) {
    unset($tab[$key]); return true;

 } else if (array_key_exists($value, $tab)){
        unset($tab[$value]); return true;

 } else {
    return false; // the $value is not in the array $tab
 }

}

ความนับถือ



4

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

if(($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
    $arr = array_values($messages);
}

การอ้างอิงอยู่ที่นี่


4

ตามความต้องการของคุณ " แต่ละค่าสามารถมีได้เพียงครั้งเดียว " ถ้าคุณเพียงแค่สนใจที่จะรักษาค่าที่ไม่ซ้ำกันในอาเรย์ของคุณarray_unique()อาจเป็นสิ่งที่คุณกำลังมองหา

การป้อนข้อมูล:

$input = array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);

ผลลัพธ์:

array(2) {
  [0] => int(4)
  [2] => string(1) "3"
}

4

หากค่าที่คุณต้องการลบนั้นอยู่หรือสามารถอยู่ในอาร์เรย์ได้ ใช้ฟังก์ชันarray_diff ดูเหมือนว่าจะทำงานได้ดีสำหรับสิ่งต่าง ๆ เช่นนี้

array_diff

$arrayWithValuesRemoved = array_diff($arrayOfData, $arrayOfValuesToRemove);

1
สิ่งนี้แตกต่างจากคำตอบนี้อย่างไร
random_user_name

4

ฉันรู้ว่านี่ไม่ได้มีประสิทธิภาพเลย แต่ง่ายเรียบง่ายและอ่านง่าย
ดังนั้นหากใครบางคนกำลังมองหาวิธีแก้ปัญหาที่ไม่แฟนซีซึ่งสามารถขยายให้ทำงานได้ด้วยค่าที่มากขึ้นหรือเงื่อนไขที่เฉพาะเจาะจงมากขึ้น .. นี่คือรหัสง่ายๆ:

$result = array();
$del_value = 401;
//$del_values = array(... all the values you don`t wont);

foreach($arr as $key =>$value){
    if ($value !== $del_value){
        $result[$key] = $value;
    }

    //if(!in_array($value, $del_values)){
    //    $result[$key] = $value;
    //}

    //if($this->validete($value)){
    //      $result[$key] = $value;
    //}
}

return $result


3

หากคุณไม่ทราบว่ากุญแจของมันหมายความว่ามันไม่สำคัญ

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

$messages=array();   
$messages[312] = 312;    
$messages[401] = 401;   
$messages[1599] = 1599;   
$messages[3] = 3;    

unset($messages[3]); // no search needed

ใช้งานได้เฉพาะกับวัตถุที่สามารถแปลงเป็นสตริงได้
Emile Bergeron


2

คุณสามารถอ้างถึงURLนี้: สำหรับฟังก์ชั่น

array-diff-key()

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_key($array1, $array2));
?>

ผลลัพธ์ก็ควรจะเป็น

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}

1

แนวคิดอื่นในการลบค่าของอาร์เรย์ให้ใช้ array_diff ถ้าฉันต้องการ

$my_array = array(1=>"a", "second_value"=>"b", 3=>"c", "d");
$new_array_without_value_c = array_diff($my_array, array("c"));

(Doc: http://php.net/manual/fr/function.array-diff.php )


3
สิ่งนี้แตกต่างจากคำตอบนี้อย่างไร
random_user_name

1

ฉันคิดว่าวิธีที่ง่ายที่สุดคือการใช้ฟังก์ชั่นที่มีลูป foreach:

//This functions deletes the elements of an array $original that are equivalent to the value $del_val
//The function works by reference, which means that the actual array used as parameter will be modified.

function delete_value(&$original, $del_val)
{
    //make a copy of the original, to avoid problems of modifying an array that is being currently iterated through
    $copy = $original;
    foreach ($original as $key => $value)
    {
        //for each value evaluate if it is equivalent to the one to be deleted, and if it is capture its key name.
        if($del_val === $value) $del_key[] = $key;
    };
    //If there was a value found, delete all its instances
    if($del_key !== null)
    {
        foreach ($del_key as $dk_i)
        {
            unset($original[$dk_i]);
        };
        //optional reordering of the keys. WARNING: only use it with arrays with numeric indexes!
        /*
        $copy = $original;
        $original = array();
        foreach ($copy as $value) {
            $original[] = $value;
        };
        */
        //the value was found and deleted
        return true;
    };
    //The value was not found, nothing was deleted
    return false;
};

$original = array(0,1,2,3,4,5,6,7,4);
$del_val = 4;
var_dump($original);
delete_value($original, $del_val);
var_dump($original);

ผลลัพธ์จะเป็น:

array(9) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [4]=>
  int(4)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
  [8]=>
  int(4)
}
array(7) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
}

1

ด้วย PHP 7.4 โดยใช้ฟังก์ชั่นลูกศร:

$messages = array_filter($messages, fn ($m) => $m != $del_val);

เพื่อให้มันเป็นอาร์เรย์ที่ไม่เชื่อมโยงห่อด้วยarray_values():

$messages = array_values(array_filter($messages, fn ($m) => $m != $del_val));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.