Xóa mục mảng theo giá trị


166

Tôi cần xóa mục mảng với giá trị đã cho:

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

Nó có thể được thực hiện theo cách ngắn hơn (hiệu quả hơn)?


Câu trả lời:


423

Nó có thể được thực hiện với một lớp lót đơn giản.

Có mảng này:

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

Bạn có thể làm:

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

Và giá trị của $arrsẽ là:

array('nice_item', 'another_liked_item')

Hy vọng nó sẽ giúp viết mã đẹp.


2
Không, nó không làm việc với mảng tham chiếu, các array_diffchức năng là không phá hủy, nó sẽ trả về một mảng mới.
Alejandro García Iglesias

2
@srcspider tại sao không? $referenced = array_diff($referenced, $items_to_remove);
Alejandro García Iglesias

1
$ được tham chiếu hiện đang trỏ đến một mảng mới, mảng bạn muốn thay đổi vẫn có các giá trị cũ.
srcspider

2
@srcspider tốt, bạn cho tôi biết những gì đang xảy ra ở đây sau đó ... codepad.org/11ZhiFP0
Alejandro García Iglesias

1
lỗi của tôi; Mánh lới quảng cáo biến đổi của php luôn làm tôi
vấp ngã

37

Tôi đang thêm một câu trả lời thứ hai. Tôi đã viết một kịch bản điểm chuẩn nhanh để thử các phương pháp khác nhau ở đây.

$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>';

Phương thức thứ ba, array_keys()với tham số tìm kiếm tùy chọn được chỉ định, dường như là phương pháp tốt nhất. Ví dụ đầu ra:

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

Đánh giá theo cách này, giải pháp tôi sẽ sử dụng sau đó sẽ là:

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

Tôi nghĩ rằng Array_search là mã dễ đọc hơn nhiều so với sử dụng phương thức Array_diff. Upvote
kendepelchin

@zombat Mình băn khoăn không biết thứ tự có liên quan gì đến kết quả không. Có thể là shuffle đưa giá trị mà chúng ta đang tìm kiếm gần hơn về phía trước hoặc kết thúc. Ngoài ra ... +1
Tướng Redneck

31

Làm thế nào về:

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

hoặc cho nhiều giá trị:

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

Điều này cũng sẽ ngăn ngừa mất chìa khóa, đó là một tác dụng phụ của array_flip().


1
sẽ không hoạt động nếu $ id là phần tử mảng đầu tiên, tốt hơn theo cách này: if (($ key = Array_search ($ id, $ items))! == false) unset ($ items [$ key]);
Marek

15

để loại bỏ $rm_valkhỏi$arr

unset($arr[array_search($rm_val, $arr)]);

8

Giải pháp mạnh nhất sẽ được sử dụng array_filter, cho phép bạn xác định chức năng lọc của riêng mình.

Nhưng một số người có thể nói rằng nó hơi quá mức, trong tình huống của bạn ...
Một foreachvòng lặp đơn giản để đi qua máng và loại bỏ mục bạn không muốn là đủ.

Một cái gì đó như thế này, trong trường hợp của bạn, có lẽ nên thực hiện mẹo:

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

Hãy thử mảng_search ()


3
Tôi chỉ đọc tài liệu và khuyên bạn nên sử dụng Array_keys () để tìm tất cả các khóa liên quan đến một giá trị.
Savageman

@Savageman - Đồng ý. Tôi đã chạy một điểm chuẩn nhanh và array_keys()dường như thực hiện tốt hơn array_search()cho nhiệm vụ này.
zombat

6

Giải pháp của bạn chỉ hoạt động nếu bạn có các giá trị duy nhất trong mảng của mình

Xem:

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

Một cách tốt hơn sẽ không được đặt với Array_search , trong một vòng lặp nếu cần thiết.


bạn đúng, nhưng trong trường hợp cụ thể này, tôi khá chắc chắn rằng các giá trị là duy nhất :)
Marek

5

w / o lật:

<?php
foreach ($items as $key => $value) {
    if ($id === $value) {
        unset($items[$key]);
    }
}

5
function deleteValyeFromArray($array,$value)
{
   foreach($array as $key=>$val)
   {
      if($val == $value)
      {
         unset($array[$key]);
      }
   }
   return $array;
}

4

Bạn có thể sử dụng hàm Array_splice cho thao tác này Ref: Array_splice

array_splice($array, array_search(58, $array ), 1);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.