foreach 루프 내의 배열에서 객체를 삭제하는 방법은 무엇입니까?


140

객체 배열을 반복하고 'id'속성에 따라 객체 중 하나를 삭제하려고하지만 코드가 작동하지 않습니다.

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

어떤 제안이라도. 감사.


답변:


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
동일한 배열의 foreach 루프 내에서 배열의 요소를 제거하는 것이 안전합니까?
Olivier Pons

25
@Oliver : 일반적으로 예기치 않은 동작을 생성하지만 PHP의 foreach로 안전하게 수행 할 수 있습니다. 테스트를 위해 여기를 읽으십시오 : php.net/manual/en/control-structures.foreach.php#88578
pangon

1
@Paritosh 오래 전에 게시 한 것을 알고 있지만 PHP는 연관 배열을 사용하기 때문입니다. 따라서 삭제 된 색인이 있으며 JSON으로 객체로 인코딩됩니다. 연관 배열은 "사전"이므로 의미가 있습니다. 오는 사람을 도울 수 있습니다.
Ryan O'Donnell

1
당신은 정말로 각각에 대해 두 번째를해야합니까? 객체의 원하는 'id'속성을 쿼리 할 수 ​​없습니까? 다른 소품을 모두 확인해야하는 이유.
htafoya

3
@ htafoya 아니오 당신은 방금 if(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); }그의 코드를 복사하고 수정하여 그에게 unset올바르게 하는 방법을 보여줄 때 생각할 수 있습니다 .
prodigitalson

2

설정 해제에 대한 구문이 유효하지 않은 것 같습니다. 다시 색인화가 없으면 나중에 문제가 발생할 수 있습니다. PHP 배열 섹션을 참조하십시오 .

올바른 구문은 위에 나와 있습니다. 또한 재 인덱싱을위한 배열 값 을 염두에두고 이전에 삭제 한 항목을 인덱싱하지 마십시오.


2

foreach값에 대한 참조를 사용할 수도 있습니다 .

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

9
$ element (foreach 안팎으로 사용)는 배열의 각 요소에 대한 참조 일뿐입니다. unset ($ element)은 참조를 깨뜨릴 것이고 참조 된 요소를 배열에서 파괴하지 않습니다.
Nicholas

3
@Dev_NIX $element = null는 작동하지 않습니다. 길이 $array는 동일합니다. 단지 null 만 포함합니다.
Nico Westerdale

1

이 트릭을해야합니다 .....

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

1

주요 답변에주의하십시오.

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

그리고 함수를 호출

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

그것은 반환

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

대신에

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

unset은 배열을 다시 색인화하지 않기 때문입니다.

다시 색인을 생성합니다. (필요한 경우)

$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

나는 PHP 프로그래머가 아니지만 C #에서는 배열을 반복하는 동안 배열을 수정할 수 없다고 말할 수 있습니다. foreach 루프를 사용하여 요소 또는 제거 할 요소의 색인을 식별 한 다음 루프 뒤의 요소를 삭제하려고 할 수 있습니다.


14
대부분의 언어에서는 나쁜 습관이지만 PHP의 배열은 기본적으로 순서대로 반복 할 수있는 연관 배열입니다. 이전 요소를 삭제해도 그 뒤에 오는 요소의 키는 변경되지 않습니다.
Ignacio Vazquez-Abrams

22
실제로 foreach가 내부적으로 사용하는 배열이 원래 배열의 복사본이기 때문에 허용됩니다. 이렇게하면 원래 배열을 수정하는 것이 완벽하게 안전합니다.
Juan

68
실제로, PHP는 완전히 지옥이기 때문에 허용됩니다.
Eric G
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.