PHP-객체 배열에서 객체 속성별로 항목 찾기


174

배열은 다음과 같습니다.

[0] => stdClass Object
        (
            [ID] => 420
            [name] => Mary
         )

[1] => stdClass Object
        (
            [ID] => 10957
            [name] => Blah
         )
...

그리고라는 정수 변수가 $v있습니다.

ID속성에 $v값 이있는 객체가있는 배열 항목을 어떻게 선택할 수 있습니까?

답변:


189

배열을 반복하고 특정 레코드를 검색하거나 (한 번만 검색 가능) 다른 연관 배열을 사용하여 해시 맵을 작성합니다.

전자의 경우 이와 같은

$item = null;
foreach($array as $struct) {
    if ($v == $struct->ID) {
        $item = $struct;
        break;
    }
}

- 후자에 대한 자세한 내용은이 질문 이후 답변을 참조 여러 인덱스에 의해 참조 PHP 배열


3
$ item을 null로 설정하지 않아도됩니다.
dAm2K

32
찾는 항목이 배열에없는 경우입니다. 또는 isset($item)변수를 올바르게 초기화하는 것을 선호합니다
Phil

3
키 값을 문자열로 설정 한 사용자에게는if($v == $struct["ID"]){...
wbadart

67

YurkamTim 이 옳습니다. 수정 만 필요합니다 :

function ($) 다음에 "use (& $ searchedValue)"를 사용하여 외부 변수에 대한 포인터가 필요하면 외부 변수에 액세스 할 수 있습니다. 또한 수정할 수 있습니다.

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use (&$searchedValue) {
        return $e->id == $searchedValue;
    }
);

2
수정에 대해서는 옳고 깔끔한 방법이지만 객체를 반복하는 것과 비교하여 속도를 테스트했습니다. @ phil이 지적한 것처럼 array_filter 도이 작업을 수행하기 때문에이 방법은 약 5 배 이상. 내 테스트 객체는 크지 않으므로 더 나빠질 수 있습니다.
Nicolai

9
&가져올 때 필요하지 않습니다 $searchedValue폐쇄 범위에. 는 &경우에만 필요 참조 만드는 데 사용되는 $searchedValue폐쇄 내부 개질되었습니다.
Stefan Gehrig

멋지다. PHP가 그런 일을 할 수 있다는 것을 몰랐습니다. global함수를 사용하여 데이터를 공유하는 것이 유일한 방법 이라고 생각했습니다 ! 그러나 이것이 실제로 느리면 불행한 일입니다. :(
NoOne

13
TS가 단일 항목을 요청하면이 코드는 배열을 반환합니다.
Pavel Vlasov

57
$arr = [
  [
    'ID' => 1
  ]
];

echo array_search(1, array_column($arr, 'ID')); // prints 0 (!== false)

3
왜 이것이 선호되지 않는지 잘 모르겠습니다. 두 개의 함수를 호출하기 때문입니까?
doz87

1
나는 파티에 너무 늦었다 고 생각합니다.) 루프와 중단없이 부족하고 가독성이 합리적입니다. 그러나 아직 벤치마킹하지 않았습니다. PHP에는 동일한 것을 달성하기위한 많은 옵션이 있습니다.
Tim

3
매우 우아한 솔루션. PHP 7의 객체 배열에서도 작동합니다. PHP 5의 경우 : array_search ($ object-> id, array_map (function ($ object) {return $ object-> id;}, $ objects)); PHP 7의 경우 : array_search ($ object-> id, array_column ($ objects, 'id'));
Mike

3
op가 객체 배열을 요구하고이 응답자가 순수한 배열 만 처리하기 때문에 이것은 선호되는 대답이 아닙니다.
Dwza

8
맞지 않습니다. 이 코드는 객체 배열 / 비평면 배열
Tim

31

더 우아한 해결책을 찾았 습니다 . 질문에 적응하면 다음과 같이 보일 수 있습니다.

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use ($searchedValue) {
        return $e->id == $searchedValue;
    }
);

16
+1이지만 array_filter배열을 반환하며 발견 된 첫 번째 값에서 멈추지 않습니다.
Carlos Campderrós

4
$searchedValue함수 내부를 인식하지 못합니다 . 그러나 외부에 있습니다.
M. Ahmad Zafar

4
우선,이 코드는 $searchedValue클로저 범위를 벗어난 것처럼 작동하지 않습니다 . 둘째, 이러한 배열 방법이 어떻게 작동한다고 생각하십니까? 그것들은 모두 배열을 내부적으로 반복합니다
Phil

1
멀티 코어의 시간에,이 - 불행히도 다른 프로그래밍 환경은 - 루프 반드시 위에 병렬로 처리 될 수있다
FloydThreepwood

3
$searchedValue쓰기 필요 를 사용하려면function ($e) use ($searchedValue) {
Vilintritenmert

20

array_column 을 사용 하여 다시 색인을 생성하면 여러 번 찾아야 할 경우 시간이 절약됩니다.

$lookup = array_column($arr, NULL, 'id');   // re-index by 'id'

그럼 당신은 단순히 $lookup[$id]마음대로 할 수 있습니다 .


3
이것은 가장 직관적이지는 않더라도 가장 놀라운 대답이었습니다 ...
Thiago Natanael

11
class ArrayUtils
{
    public static function objArraySearch($array, $index, $value)
    {
        foreach($array as $arrayInf) {
            if($arrayInf->{$index} == $value) {
                return $arrayInf;
            }
        }
        return null;
    }
}

원하는 방식으로 사용하면 다음과 같습니다.

ArrayUtils::objArraySearch($array,'ID',$v);


7

@YurkaTim 의 작은 실수를 해결하면 솔루션이 나를 위해 작동하지만 다음을 추가합니다 use.

$searchedValue함수 내에서 사용하려면 use ($searchedValue)함수 매개 변수 뒤에 하나의 솔루션이있을 수 있습니다 function ($e) HERE.

array_filter함수는 반환 $neededObject조건이 다음과 같은 경우 에만 반환됩니다 .true

경우 $searchedValue문자열이나 정수 :

$searchedValue = 123456; // Value to search.
$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use ($searchedValue) {
        return $e->id == $searchedValue;
    }
);
var_dump($neededObject); // To see the output

$searchedValue목록을 확인 해야하는 배열 인 경우 :

$searchedValue = array( 1, 5 ); // Value to search.
$neededObject  = array_filter(
    $arrayOfObjects,
    function ( $e ) use ( $searchedValue ) {
        return in_array( $e->term_id, $searchedValue );
    }
);
var_dump($neededObject); // To see the output

1
마지막 줄은 var_dump($neededObject);:)
Sliq

3

때로는 array_reduce () 함수를 사용 하여 검색을 수행하는 것을 좋아 합니다. array_filter ()와 비슷하지만 검색된 배열에는 영향을 미치지 않으므로 동일한 객체 배열에서 여러 번 검색 할 수 있습니다 .

$haystack = array($obj1, $obj2, ...); //some array of objects
$needle = 'looking for me?'; //the value of the object's property we want to find

//carry out the search
$search_results_array = array_reduce(
  $haystack,

  function($result_array, $current_item) use ($needle){
      //Found the an object that meets criteria? Add it to the the result array 
      if ($current_item->someProperty == $needle){
          $result_array[] = $current_item;
      }
      return $result_array;
  },
  array() //initially the array is empty (i.e.: item not found)
);

//report whether objects found
if (count($search_results_array) > 0){
  echo "found object(s): ";
  print_r($search_results_array[0]); //sample object found
} else {
  echo "did not find object(s): ";
}

1
results_array를 추가하는 조건부 내에 오타가 있습니다. : 그것은이 있어야한다if ($current_item->someProperty == $needle){ $result_array[] = $current_item; }
adrum

조정되었습니다. @adrum 감사합니다!
yuvilio

1

나는 일종의 Java 키 맵으로 이것을했다. 그렇게하면 매번 객체 배열을 반복 할 필요가 없습니다.

<?php

//This is your array with objects
$object1 = (object) array('id'=>123,'name'=>'Henk','age'=>65);
$object2 = (object) array('id'=>273,'name'=>'Koos','age'=>25);
$object3 = (object) array('id'=>685,'name'=>'Bram','age'=>75);
$firstArray = Array($object1,$object2);
var_dump($firstArray);

//create a new array
$secondArray = Array();
//loop over all objects
foreach($firstArray as $value){
    //fill second        key          value
    $secondArray[$value->id] = $value->name;
}

var_dump($secondArray);

echo $secondArray['123'];

산출:

array (size=2)
  0 => 
    object(stdClass)[1]
      public 'id' => int 123
      public 'name' => string 'Henk' (length=4)
      public 'age' => int 65
  1 => 
    object(stdClass)[2]
      public 'id' => int 273
      public 'name' => string 'Koos' (length=4)
      public 'age' => int 25
array (size=2)
  123 => string 'Henk' (length=4)
  273 => string 'Koos' (length=4)
Henk

아, id를 기준으로 배열을 재색 인화! 나는 이것을 일반적으로하고 일을 더 좋게 만듭니다.
Kzqai

1

첫 번째 가치를 즉시 얻는 방법 :

$neededObject = array_reduce(
    $arrayOfObjects,
    function ($result, $item) use ($searchedValue) {
        return $item->id == $searchedValue ? $item : $result;
    }
);

0

빠른 이진 검색 알고리즘을 사용 하여이 문제를 효율적으로 해결하는 데 사용하는 내용을 게시했습니다. https://stackoverflow.com/a/52786742/1678210

나는 같은 대답을 복사하고 싶지 않았습니다. 다른 사람이 약간 다르게 요청했지만 대답은 동일합니다.

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