PHP-オブジェクトの配列からオブジェクトプロパティでエントリを検索する


174

配列は次のようになります。

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

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

そして私はと呼ばれる整変数を持っています $v

IDプロパティが$v値を持つオブジェクトを持つ配列エントリをどのように選択できますか?

回答:


189

配列を反復して特定のレコードを検索するか(1回限りの検索でもOK)、別の連想配列を使用してハッシュマップを作成します。

前者の場合、このようなもの

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

後者の詳細については、この質問とその後の回答を参照してください- 複数のインデックスによるPHP配列の参照


3
$ itemをnullに設定する必要はありません。
dAm2K 2012

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つかかります倍長い。私のテストオブジェクトは大きなものではないため、さらに悪化する可能性があります。
ニコライ

9
&インポート時に必要とされていない$searchedValue閉鎖スコープに。&場合にのみ必要とされる基準を作成するために使用される$searchedValue閉鎖内部修飾されているが。
Stefan Gehrig

カッコいい。PHPがそのようなことをできるとは知りませんでした。global関数を使ってデータを共有することが唯一の使い方だと思いました!しかし、これが本当に遅いのは残念です。:(
NoOne

13
TSは単一のエントリを要求しました。このコードは配列を返します。
Pavel Vlasov 2017

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

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

3
なぜこれが望ましい答えではないのかわかりません。2つの関数を呼び出しているからですか?
doz87 2018

1
パーティーには遅すぎたと思います;)ループや中断がないため、その欠如と読みやすさが合理的です。しかし、まだそれをベンチマークしていません。PHPには、同じことを行うための多くのオプションがあります。
Tim

3
非常にエレガントなソリューション。PHP 7のオブジェクトの配列でも機能します。PHP5の場合: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は配列を返し、最初に見つかった値で停止しません。
CarlosCampderrós2013

4
$searchedValue関数内では認識していません。しかし、それは外です。
M. Ahmad Zafar 2013

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
これは、最も直感的でなくても、最も驚くべき答えでした...
チアゴナタナエル

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)関数パラメーターの後に1つの解決策があります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 2016

1

最初の値を即座に取得する方法:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.