Làm thế nào để bạn loại bỏ một phần tử mảng trong một vòng lặp foreach?


127

Tôi muốn lặp qua một mảng với foreachđể kiểm tra xem giá trị có tồn tại không. Nếu giá trị tồn tại, tôi muốn xóa phần tử có chứa nó.

Tôi có đoạn mã sau:

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

Tôi không biết cách xóa phần tử sau khi tìm thấy giá trị. Làm thế nào để tôi xóa nó?

Tôi phải sử dụng foreachcho vấn đề này. Có thể có những lựa chọn thay thế foreach, và bạn được chào đón để chia sẻ chúng.

Câu trả lời:


219

Nếu bạn cũng nhận được chìa khóa, bạn có thể xóa mục đó như thế này:

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

3
Một số thông tin bổ sung về tối ưu hóa bằng cách sử dụng $key => &$tag_name stackoverflow.com/a/2008893/922522
Justin

5
Lưu ý rằng các mảng được lập chỉ mục với các mục không được đặt có thể được biểu diễn dưới dạng các đối tượng thay vì các mảng sau a json_encode(). Bạn có thể giải quyết điều này với $display_related_tags = array_values ($display_related_tags);sau foreachvòng lặp.
Márton Tamás

Lưu ý rằng mẹo ở đây là thêm giá trị vào vòng lặp foreach ;-)
Mr Washington

5
Vui lòng xem @Neils trả lời. Bạn sẽ gặp phải các lỗi không mong muốn, đặc biệt nếu bạn làm việc với Array of stdClass. Bạn có thích hành vi bất ngờ? Tôi không.
happy_marmoset

@happy_marmoset Câu trả lời của Neils không có ích. Đoạn trích $projects = array_filter($projects, function ($project) { return count($project->roles) > 0; });nó chuyển đổi kết quả thành đối tượng.
Paritosh

36

Một giải pháp tốt hơn là sử dụng array_filterchức năng:

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

Như tài liệu php đọc:

Vì foreach dựa vào con trỏ mảng bên trong trong PHP 5, việc thay đổi nó trong vòng lặp có thể dẫn đến hành vi không mong muốn.

Trong PHP 7, foreach không sử dụng con trỏ mảng bên trong.


Lưu ý rằng tham số thứ 3 phải là ARRAY_FILTER_USE_KEY để chuyển khóa dưới dạng $ e tại đây.
namezero

@namezero OK tại sao điều đó lại quan trọng ở đây?
AbraCadaver

@AbraCadaver Từ tài liệu ( php.net/manual/en/feft.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. Điều đó nói rằng, đọc lại câu trả lời trong trường hợp này tất nhiên sẽ không quan trọng như bạn yêu cầu.
namezero

Quan trọng Nếu bạn quan tâm đến việc giữ mảng như là mảng đã ra lệnh, bạn cần gọi display_related_tags = array_values(display_related_tags);sau nó.
Guyaloni

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

3
'unlink' hủy liên kết các tệp, nó không liên quan gì đến các biến hoặc cụ thể hơn là các mảng. Có lẽ bạn có nghĩa là 'không đặt'?
amn

6

Thay vì thực hiện vòng lặp foreach () trên mảng, sẽ nhanh hơn khi sử dụng Array_search () để tìm khóa thích hợp. Trên các mảng nhỏ, tôi sẽ đi với foreach để dễ đọc hơn, nhưng đối với các mảng lớn hơn hoặc mã thường được thực thi, điều này sẽ tối ưu hơn một chút:

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

Toán tử biên dịch chặt chẽ! == là cần thiết, bởi vì Array_search () có thể trả về 0 là chỉ mục của $ không mong muốn.

Ngoài ra, ví dụ trên sẽ chỉ xóa giá trị đầu tiên $ không mong muốn, nếu $ không mong muốn có thể xảy ra nhiều hơn một lần trong mảng $, Bạn nên sử dụng mảng_keys (), để tìm tất cả chúng:

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

Kiểm tra http://php.net/manual/en/feft.array-search.php để biết thêm thông tin.


0

nếu bạn có kịch bản trong đó bạn phải loại bỏ nhiều hơn thì một giá trị từ mảng foreach trong trường hợp này bạn phải truyền giá trị bằng cách tham chiếu cho từng trường hợp: Tôi cố gắng giải thích kịch bản này:

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]);

                        }
               }
}

trong vòng lặp thứ hai, bạn muốn hủy đặt các mục vòng lặp đầu tiên không xuất hiện lại trong lần lặp cho mục đích hiệu năng hoặc sau đó không được đặt từ bộ nhớ vì trong bộ nhớ chúng có mặt và sẽ xuất hiện trong các lần lặp.


0

Đã có câu trả lời đưa ra ánh sáng về cách bỏ đặt. Thay vì lặp lại mã trong tất cả các lớp của bạn tạo ra chức năng như bên dưới và sử dụng nó trong mã bất cứ khi nào cần thiết. Trong logic kinh doanh, đôi khi bạn không muốn để lộ một số thuộc tính. Vui lòng xem bên dưới một cuộc gọi lót để loại bỏ

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;
}

Gọi như:

removeKeysFromAssociativeArray($arrValues, $keysToRemove);

-1

Như đã được đề cập, bạn muốn thực hiện một cuộc thảo luận với khóa và bỏ đặt bằng cách sử dụng khóa - nhưng lưu ý rằng việc thay đổi một mảng trong khi lặp lại nói chung là một ý tưởng tồi, mặc dù tôi không chắc chắn về các quy tắc của PHP về điều này ngay.


2
Một foreach php sẽ thực thi trên toàn bộ mảng bất kể. Kiểm tra bỏ đặt một giá trị tiếp theo trong lần lặp. Nó sẽ lặp lại trên phần bù, nhưng giá trị sẽ là null.
Kevin Peno

Nếu bạn không đột biến một mảng trong quá trình lặp thì làm thế nào để đột biến một mảng? Có thể là trung bình foreachhoặc forxây dựng thay vì lặp đi lặp lại nói chung?
Gherman

Đây là một nhận xét về một câu trả lời khác hơn là một câu trả lời trong chính nó.
Râu nham hiểm
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.