Làm thế nào để xóa đối tượng từ mảng bên trong vòng lặp foreach?


140

Tôi lặp qua một mảng các đối tượng và muốn xóa một trong các đối tượng dựa trên thuộc tính 'id', nhưng mã của tôi không hoạt động.

foreach($array as $element) {
    foreach($element as $key => $value) {
        if($key == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($element);//this doesn't work
            unset($array,$element);//neither does this
        } 
    }
}

Bất kỳ đề xuất. Cảm ơn.


Câu trả lời:


233
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

62
Có an toàn để loại bỏ một phần tử của một mảng trong một vòng lặp foreach của cùng một mảng không?
Olivier Pons

25
@Oliver: thông thường nó sẽ tạo ra hành vi bất ngờ, nhưng bạn có thể thực hiện nó một cách an toàn với foreach trên php. Hãy đọc ở đây để kiểm tra: php.net/manual/en/control-strucenses.foreach.php#88578
pangon

1
@Paritosh Tôi biết bạn đã đăng bài này từ lâu, nhưng đó là vì PHP sử dụng các mảng kết hợp. Vì vậy, bạn có một chỉ mục đã bị xóa: và nó được mã hóa thành JSON dưới dạng Đối tượng. Có ý nghĩa, vì một mảng kết hợp là một "từ điển." Có thể giúp đỡ ai đó đi cùng.
Ryan O'Donnell

1
Bạn có thực sự cần phải làm thứ hai cho mỗi? bạn không thể truy vấn thuộc tính 'id' mong muốn của đối tượng? Tại sao kiểm tra tất cả các đạo cụ khác.
htafoya

3
@htafoya không bạn chỉ có thể làm if(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); }tôi nghĩ tại thời điểm tôi chỉ sao chép và sửa đổi mã của mình để chỉ cho anh ta cách làm unsetđúng.
prodigitalson

2

Có vẻ như cú pháp của bạn cho unset là không hợp lệ và việc thiếu reindexing có thể gây rắc rối trong tương lai. Xem: phần trên mảng PHP .

Cú pháp đúng được hiển thị ở trên. Ngoài ra, hãy ghi nhớ các giá trị mảng để giới thiệu lại, vì vậy bạn không bao giờ lập chỉ mục một cái gì đó mà bạn đã xóa trước đó.


2

Bạn cũng có thể sử dụng tài liệu tham khảo về foreachcác giá trị:

foreach($array as $elementKey => &$element) {
    // $element is the same than &$array[$elementKey]
    if (isset($element['id']) and $element['id'] == 'searched_value') {
        unset($element);
    }
}

9
$ phần tử (được sử dụng trong và ngoài foreach) chỉ là một tham chiếu đến từng phần tử trong mảng. unset (phần tử $) sẽ chỉ ngắt tham chiếu, nó không phá hủy phần tử được tham chiếu khỏi mảng của nó.
Nicholas

3
@Dev_NIX $element = nullsẽ KHÔNG hoạt động, độ dài $arrayvẫn giữ nguyên, nó sẽ chỉ chứa null
Nico Westerdale

1

Cái này cần phải dùng mẹo.....

reset($array);
while (list($elementKey, $element) = each($array)) {
    while (list($key, $value2) = each($element)) {
        if($key == 'id' && $value == 'searched_value') {
            unset($array[$elementKey]);
        }
    }
}

1

Hãy cẩn thận với câu trả lời chính.

với

[['id'=>1,'cat'=>'vip']
,['id'=>2,'cat'=>'vip']
,['id'=>3,'cat'=>'normal']

và gọi hàm

foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'cat' && $value == 'vip'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

nó trở lại

[2=>['id'=>3,'cat'=>'normal']

thay vì

[0=>['id'=>3,'cat'=>'normal']

Đó là bởi vì unset không lập chỉ mục lại mảng.

Nó reindexes. (nếu chúng ta cần nó)

$result=[];
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        $found=false;
        if($valueKey === 'cat' && $value === 'vip'){
            $found=true;
            $break;
        } 
        if(!$found) {
           $result[]=$element;
        }
    }
}

0

Tôi không phải là một lập trình viên php, nhưng tôi có thể nói rằng trong C # bạn không thể sửa đổi một mảng trong khi lặp qua nó. Bạn có thể muốn thử sử dụng vòng lặp foreach của mình để xác định chỉ mục của phần tử hoặc các phần tử cần xóa, sau đó xóa các phần tử sau vòng lặp.


14
Mặc dù nó là thực tiễn xấu trong hầu hết các ngôn ngữ, các mảng trong PHP về cơ bản là các mảng kết hợp có thể được lặp theo thứ tự. Xóa một phần tử trước đó sẽ không thay đổi các khóa của phần tử đi sau nó.
Ignacio Vazquez-Abrams

22
Trên thực tế, điều đó được cho phép bởi vì mảng mà foreach sử dụng bên trong là một bản sao của mảng ban đầu. Bằng cách đó, sửa đổi các mảng ban đầu là hoàn toàn an toàn.
Juan

68
Trên thực tế, điều đó được cho phép bởi vì php khó hiểu như mọi thứ.
Eric G
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.