PHP-从对象数组中按对象属性查找条目


174

该数组如下所示:

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

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

我有一个名为的整数变量$v

如何选择具有对象的数组条目,其中的ID属性具有$v值?

Answers:


188

您可以迭代数组,搜索特定记录(一次只能搜索一次),也可以使用另一个关联数组来构建哈希图。

对于前者,像这样

$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 2015年

67

YurkamTim是正确的。它只需要修改:

在function($)之后,您需要通过“ use(&$ searchedValue)”来指向外部变量的指针,然后才能访问该外部变量。您也可以修改它。

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

2
您对修改是正确的,它是一种整洁的方法,但是与迭代遍历对象相比,我测试了速度-您自己,因为就像@phil指出的那样,array_filter也正在执行此操作-该方法大约需要五个更长的时间。我的测试对象不是一个大对象,因此可能会变得更糟。
Nicolai 2014年

9
&导入时不需要$searchedValue进入封闭范围。该&用于创建如果其仅需要一个参考$searchedValue已被封闭的内部改性。
Stefan Gehrig

这很酷。我不知道PHP可以做这样的事情。我以为使用global是唯一的功能共享数据!但可惜的是,这确实很慢。:(
NoOne

13
TS要求输入一个条目,此代码返回一个数组。
帕维尔·弗拉索夫

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'));
麦克,

3
这不是首选的应答者,因为op要求对象数组,而该应答者仅处理纯数组。
德乌扎

8
那是不正确的。此代码处理对象数组/非平面数组
蒂姆

30

我在这里找到了更优雅的解决方案。适应了这个问题,看起来可能像:

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

16
+1但array_filter返回一个数组,并且不会在找到的第一个值处停止。
卡洛斯·坎德罗斯(CarlosCampderró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 Natanael19年

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
您的条件中有一个错字,您要在其中添加result_array。应该是这样的:if ($current_item->someProperty == $needle){ $result_array[] = $current_item; }
adrum

已调整。谢谢@adrum!
yuvilio '17

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重新索引数组!我通常这样做,这会使事情变得更好。
卡扎伊

1

立即获得第一价值的方法:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.