PHP-객체 배열에서 속성 추출


128

고양이 개체의 배열이 있습니다.

$cats = Array
    (
        [0] => stdClass Object
            (
                [id] => 15
            ),
        [1] => stdClass Object
            (
                [id] => 18
            ),
        [2] => stdClass Object
            (
                [id] => 23
            )
)

한 줄에 고양이 ID 배열을 추출하고 싶습니다 (함수도 루프도 아님).

array_walkwith 를 사용 create_function하려고했지만 어떻게해야할지 모르겠습니다.

어떤 생각?


결과를 한 줄로 할당 할 수 있기 때문에 루프를 사용하고 싶지 않습니다. $ cats_id = myfunction ($ cats); / * 반환해야합니다 Array (15, 18, 23) * /
abernier

답변:


150

PHP 5.5 이상이 있는 경우 가장 좋은 방법은 내장 함수를 사용하는 것입니다 array_column().

$idCats = array_column($cats, 'id');

하지만 아들은 배열이거나 배열로 변환되어야합니다.


12
이것은 실제로 가장 좋은 대답이다
드미트리 Buslaev

1
최상의 솔루션, 그러나 PHP 5.5 이상에서만 사용 가능
Ludo-기록 해제

2
어쨌든 5.5로 더 이상 코딩하는 사람은 없습니다. 3.5 세 프로그래밍 언어 버전 ...
Toskan

11
때문에이 솔루션은 질문에 대답하지 않는 array_column작동하지 않습니다 arrayobject모든에서의. PHP 7.0.0이 가능하기 때문에 : stackoverflow.com/a/23335938/655224
algorhythm

1
개체 속성에 공개 액세스 권한이있는 경우에만 작동합니다.
Karol Gasienica

154

경고 create_function() 는 PHP 7.2.0부터 더 이상 사용되지 않습니다. 이 기능에 의존하는 것은 매우 권장되지 않습니다.

array_map()기능을 사용할 수 있습니다 .
이렇게해야합니다.

$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);

54
이것은 올바른 솔루션이며 모든 곧 테이너가 "무슨 일" 'D 될 것이라는 사실로 이어질 것입니다 : D
안드레아스 클링

4
이 솔루션에 대해 내가 싫어하는 유일한 점은 create_function을 사용하는 것입니다.
Ionuț G. Stan

4
람다 함수를 사용할 수는 있지만 PHP 5.3을 실행하는 사람은 많지 않습니다.
Greg

26
여기에 있습니다. $project_names = array_map(function($project) { return $project->name ;}, $projects );그러나이 블로그 게시물 에서는이 방식이 2.5 배 느리거나 메모리를 많이 사용할 수 있다고 언급 했습니다 .
Relequestual

7
create_function메모리로 함수를 만들 때마다 늘고 있다는 것을 알았 습니다. 당신이 무한 루프와 programm에를 작성하고 호출하는 경우 array_map와를 create_function그 안에 당신은 항상 얻을 것이다 Out of memory...오류 언젠가. 그래서 사용하지 않는 create_function사용array_map(function($o) { return $o->id; }, $objects);
algorhythm

87

솔루션은 사용중인 PHP 버전에 따라 다릅니다. 최소한 두 가지 솔루션이 있습니다.

먼저 (최신 PHP 버전)

@JosepAlsina가 전에 말했듯이 가장 짧은 해결책은 array_column다음과 같이 사용 하는 것입니다.

$catIds = array_column($objects, 'id');

주의 : 질문에 사용 array\stdClasses를 포함하는 반복은 PHP 버전에서만 가능합니다 >= 7.0. 그러나 array포함하는 arrays를 사용하면 PHP부터 동일한 작업을 수행 할 수 있습니다 >= 5.5.

두 번째 (이전 PHP 버전)

@Greg는 이전 PHP 버전에서 다음을 수행 할 수 있다고 말했습니다.

$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);

그러나주의하십시오 : 최신 PHP 버전에서는 다음과 같이 s >= 5.3.0를 사용하는 것이 좋습니다 Closure.

$catIds = array_map(function($o) { return $o->id; }, $objects);


차이점

첫 번째 솔루션은 새로운 기능을 생성하여 RAM에 넣습니다. 가비지 수집기는 어떤 이유로 든 메모리에서 이미 생성되고 이미 호출 된 함수 인스턴스를 삭제하지 않습니다. 그리고 사실에 관계없이 생성 된 함수 인스턴스는 포인터가 없기 때문에 다시 호출 할 수 없습니다. 다음에이 코드를 호출하면 동일한 함수가 다시 생성됩니다. 이 행동은 천천히 당신의 기억을 채 웁니다 ...

비교를위한 메모리 출력이있는 두 예 :

나쁜

while (true)
{
    $objects = array_map(create_function('$o', 'return $o->id;'), $objects);

    echo memory_get_usage() . "\n";

    sleep(1);
}

// the output
4235616
4236600
4237560
4238520
...

좋은

while (true)
{
    $objects = array_map(function($o) { return $o->id; }, $objects);

    echo memory_get_usage() . "\n";

    sleep(1);
}

// the output
4235136
4235168
4235168
4235168
...


여기에서도 논의 할 수 있습니다.

메모리 누수?! 'array_map'내에서 'create_function'을 사용할 때 Garbage Collector가 제대로 작동합니까?


비록 내가 PHP 7.2를 사용하고 있지만 네임 스페이스 클래스 객체를 사용하고 빈 배열을 반환하는 경우 솔루션이 작동하지 않는 것 같습니다.
Muhammad Omer Aslam

익스플로잇을 게시 할 수 있습니까? 컨텍스트를 더 잘 이해하기위한 짧은 스 니펫?
algorhythm

예를 들어, dropbox API SDK에서 반환 한 모델 객체 목록이있는 이 스 니펫을 참조하세요 array_column.이 배열 에서 사용하려고 하면 항상 공백을 반환하는 반면 스 니펫은 올바르게 작동하며 둘 다 두 번째 스 니펫에서 액세스 할 수있는 protected 속성을가집니다. 뿐. 네임 스페이스 이외의 다른 이유를 찾을 수 없습니다.
Muhammad Omer Aslam

내가 쓸 때 object내 솔루션에 내 말은 object없습니다 Object. 소문자 object는 단순 객체를 나타냅니다 \stdClass. 그게 문제 일 수도 있습니다. 당신이 있습니까 ObjecttoArray방법을? 이것을 사용하십시오. 단순함 objectarray거의 동일합니다. 다음 불변이 유효해야합니다 : ((object)(array)$o) === $o. __get메서드를 구현할 때 모든 사람이 클래스 속성에 액세스 할 수 있도록합니다. 이것은 예상 된 동작 일 수 있습니다. 하지만 array<Object>예를 들어 with array_mapand call toArray(존재하는 경우)을 반복 할 수도 있습니다. 그러면 IT도 작동합니다
algorhythm

내가 제공 한 두 번째 스 니펫은 php, net에서 왔으며 첫 번째 스 니펫에서와 동일한 Class 객체를 사용합니다. 아마도 당신이 맞을 수도 있습니다. 아마도 다른 스 니펫을 배열로 변환하여 시도 할 것입니다.
Muhammad Omer Aslam

4
function extract_ids($cats){
    $res = array();
    foreach($cats as $k=>$v) {
        $res[]= $v->id;
    }
    return $res
}

한 줄로 사용하십시오 .

$ids = extract_ids($cats);

1
감사합니다 SilentGhost,하지만 내 질문은 루프를 사용하지 않고 단 하나의 명령으로 $ res를 얻으려고합니다 ...
abernier

2
어떤 차이가 있습니까? 이것은 얻는 것만 큼 간단합니다. 아마도 같은 것을 사용하여 더 많은 줄을 사용할 것 array_walk입니다.
deceze

우아하고 간단하며 간결한 솔루션 인 @deceze는 더 좋아 보입니다. 특히이 작업처럼 설명 할 수있는 것 (예 : 많은 공간과 주석을 사용할 수있는 사용자 지정 논리가 아님)의 경우 더욱 그렇습니다. 나에게 그것은 큰 차이를 만듭니다.
찰리 Dalsass

3

암호

<?php

# setup test array.
$cats = array();
$cats[] = (object) array('id' => 15);
$cats[] = (object) array('id' => 18);
$cats[] = (object) array('id' => 23);

function extract_ids($array = array())
{
    $ids = array();
    foreach ($array as $object) {
        $ids[] = $object->id;
    }
    return $ids;
}

$cat_ids = extract_ids($cats);
var_dump($cats);
var_dump($cat_ids);

?>

산출

# var_dump($cats);
array(3) {
  [0]=>
  object(stdClass)#1 (1) {
    ["id"]=>
    int(15)
  }
  [1]=>
  object(stdClass)#2 (1) {
    ["id"]=>
    int(18)
  }
  [2]=>
  object(stdClass)#3 (1) {
    ["id"]=>
    int(23)
  }
}

# var_dump($cat_ids);
array(3) {
  [0]=>
  int(15)
  [1]=>
  int(18)
  [2]=>
  int(23)
}

나는 루프를 사용하는 것을 알고 있지만 가장 간단한 방법입니다! 그리고 함수를 사용하면 여전히 한 줄로 끝납니다.


사람들이 이와 같은 간단한 솔루션을 선택하지 않는 이유를 이해하지 못합니다. 저에게 물어 보면 이런 식으로하는 것이 논리적으로 보입니다.
Tom Dyer


3

경고 create_function() 는 PHP 7.2.0부터 더 이상 사용되지 않습니다. 이 기능에 의존하는 것은 매우 권장되지 않습니다.

PHP의 내장 루프는 해석 된 루프보다 빠르기 때문에 실제로 한 줄로 만드는 것이 좋습니다.

$result = array();
array_walk($cats, create_function('$value, $key, &$result', '$result[] = $value->id;'), $result)


0
    $object = new stdClass();
    $object->id = 1;

    $object2 = new stdClass();
    $object2->id = 2;

    $objects = [
        $object,
        $object2
    ];

    $ids = array_map(function ($object) {
        /** @var YourEntity $object */
        return $object->id;
        // Or even if you have public methods
        // return $object->getId()
    }, $objects);

출력 : [1, 2]


0

create_function()함수는 php v7.2.0부터 더 이상 사용되지 않습니다 . array_map()주어진대로 사용할 수 있습니다 .

function getObjectID($obj){
    return $obj->id;
}

$IDs = array_map('getObjectID' , $array_of_object);

또는 array_column()column_key로 식별되는 입력의 단일 열에서 값을 반환하는 함수를 사용할 수 있습니다 . 선택적으로 입력 배열의 index_key 열 값에 의해 반환 된 배열의 값을 인덱싱하기 위해 index_key가 제공 될 수 있습니다. 주어진대로 array_column을 사용할 수 있습니다.

$IDs = array_column($array_of_object , 'id');
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.