Php 在数组中查找单个元素,而不在数组中循环

Php 在数组中查找单个元素,而不在数组中循环,php,arrays,object,Php,Arrays,Object,我有一个数组,其中存储了对象。我想获取数组中名为test-song-poll-02的对象。我知道我可以循环遍历它并执行条件检查每个对象中的名称,但我想知道是否有一个数组/对象php函数可以返回name='test-song-poll-03'的对象 Array ( [0] => stdClass Object ( [name] => test-song-poll-01 [description] => tes

我有一个数组,其中存储了对象。我想获取数组中名为test-song-poll-02的对象。我知道我可以循环遍历它并执行条件检查每个对象中的名称,但我想知道是否有一个数组/对象php函数可以返回name='test-song-poll-03'的对象

Array
(
    [0] => stdClass Object
        (
            [name] => test-song-poll-01
            [description] => test-song-poll-01
            [created_at] => 2014-05-02T23:07:59Z
            [count] => stdClass Object
                (
                    [approved] => 63787
                    [pending] => 341
                    [rejected] => 78962
                    [total] => 143090
                )

            [tpm] => 12
            [approved_tpm] => 3
            [pct] => 4
        )

    [1] => stdClass Object
        (
            [name] => test-song-poll-02
            [description] => test-song-poll-02
            [created_at] => 2014-05-02T23:17:20Z
            [count] => stdClass Object
                (
                    [approved] => 9587
                    [pending] => 0
                    [rejected] => 9780
                    [total] => 19367
                )

            [tpm] => 5
            [approved_tpm] => 3
            [pct] => 1
        )

    [2] => stdClass Object
        (
            [name] => test-song-poll-03
            [description] => test-song-poll-03
            [created_at] => 2014-05-02T23:19:06Z
            [count] => stdClass Object
                (
                    [approved] => 26442
                    [pending] => 0
                    [rejected] => 36242
                    [total] => 62684
                )

            [tpm] => 25
            [approved_tpm] => 9
            [pct] => 2
        )
)
更新了我的代码以显示如何传入变量:

function get_results()
{
    $hashtag = "test-song-poll-03";
    $this->load->model('artist_model');
    $data['results'] = $this->artist_model->get_results();

    $myobject = array_filter($data['results']->streams, function($e, $hashtag) {
      return strcmp($e->name, $hashtag) == 0;
    });

    print_r($myobject);
}

您可以使用数组过滤器

$myobjects = array_filter($objects, function($e) use($hashtag) {
  return strcmp($e->name, "test-song-poll-03") == 0;
});
由于使用了匿名函数,这只适用于PHP>=5.3


如果您使用的是较旧的版本,则可以使用自己的函数。

从json格式的API获取数据并不意味着您必须以给定的格式保存数据。有几种策略比你公认的答案更有效

当前所选答案的问题是,每次使用它时,它都会在整个数据集上迭代,即使在第一次迭代中找到匹配项。我不知道你的数据集有多大,但我假设它很重要,否则你就不会问这个问题了

我也不知道有多少次你想访问数据集,你可能也不知道,但我认为这足够让你思考,或者,再一次,你不会问这个问题

假设您有一个由1000个
stdClass
对象组成的数据集,并且您请求每个对象一次,因此可以访问它1000次

现在,建议您使用的“array_filter()”方法每次必须访问所有1000个元素(它是O(n)),即总共1000000次迭代

//Access every element once using array_filter()
$objectArray = [];
$objectNames = [];
for($i = 0; $i < 1000; $i ++){
    $objName = 'object_name_' . ($i + 1);
    $objectNames[] = $objName;
    $obj = new stdClass();
    $obj->name = $objName;
    $obj->description = 'test description';
    $obj->accessed = 0;
    $objectArray[] = $obj;
}
$start = microtime(true);
foreach($objectNames as $name){
    $iterations = getObjectWithArray_Filter($name, $objectArray);
}
$end = microtime(true);
$taken = $end - $start;
echo $iterations . " iterations using array_filter() in $taken seconds<br/>\n";

我想到的第二种选择是遍历数组一次,然后将其写入关联数组。第一次遍历将是O(n),1000次迭代,此后我们将能够直接访问我们想要的元素,而不需要遍历数组,即O(1)。给我们2000次迭代,一次访问数组的每个元素

//Access every element once using Associative array
$objectArray = [];
$objectNames = [];
for($i = 0; $i < 1000; $i ++){
    $objName = 'object_name_' . ($i + 1);
    $objectNames[] = $objName;
    $obj = new stdClass();
    $obj->name = $objName;
    $obj->description = 'test description';
    $obj->accessed = 0;
    $objectArray[] = $obj;
}

$associativeArray = [];
$start = microtime(true);
foreach($objectArray as $object){
    $associativeArray[$object->name] = $object;
    $object->accessed ++;
}

foreach($objectNames as $name){
    $iterations = getObjectFromAssociativeArray($objName, $associativeArray);
}
$end = microtime(true);
$taken = $end - $start;
echo $iterations . " iterations using associative array{} in $taken seconds<br/>\n";
tl;dr
3v4l.org上的输出:-

Accessing 1000 elements once took 1000000 iterations using array_filter() in 0.5374710559845 seconds
Accessing 1000 elements once took 500500 iterations using foreach(){} in 0.2077169418335 seconds
Accessing 1000 elements once took 2000 iterations using associative array{} in 0.1438410282135 seconds

时间上的差异也很有趣。您可能需要也可能不需要像这样优化速度,但我建议您对代码进行一次有价值的更改。在任何情况下,我都会认为第一次迭代之后的迭代都比1000次或每次平均500.5次要好得多

我希望你认为这是一个有价值的练习,你的问题激发了我的兴趣,我确信你接受的答案不是你的最佳解决方案。你可能仍然认为是这样,但我提出这一点作为替代

实现这一点的最简单方法是使用某种对象存储/工厂:-

class ObjectStore
{
    private $decoded;
    private $asssocArray;

    public function __construct($jsonEncodedObjects)
    {
        $this->decoded = json_decode($jsonEncodedObjects);
    }

    public function getObject($objectName)
    {
        if(!$this->asssocArray){
            foreach($this->decoded as $object){
                $this->asssocArray[$object->name] = $object;
            }
        }
        return $this->asssocArray[$objectName];
    }
}
这样,您对对象的第一个请求是O(n),随后的请求将是O(1)

要在代码中使用此选项,请执行以下操作:-

$objectStore = new ObjectStore(getJsonEncodedData());

$hashtag = "test-song-poll-03";
$myObject = $objectStore->getObject($hashtag);

你能控制数组的构造方式吗?不,我是从api中提取json数据。你能把“test-song-poll-03”作为一个变量传递到那里吗?我尝试在传递$e的函数中将其作为参数传递,但它给了我一个错误:警告:中缺少Home:{closure}()的参数2,注意:中的未定义变量:hashtag。我试图传递的变量是$hashtag。我更新了代码以向您展示我是如何使用您的代码的。我不知道这一点,但您可以使用“global$hashtag;”进行尝试大概我将测试它。我编辑了我的答案,你可以使用“use($hashtag)”将变量传递到闭包中。这段代码有点误导,它返回一个数组,而不是一个对象。此数组包含具有相应名称的所有(!)对象,但也可以有零个或多个这样的值。除此之外,它并不能避免在数组中循环,这在计算上可能非常昂贵。如果这很重要,那么您需要一个数组,该数组可以从搜索的名称映射到相应的对象(或对象?),类似于数据库索引。他从API中提取数据,无法更改数组,因此没有其他方法。您是对的,OP没有要求最佳选项,他要求的是PHP中的函数。如果你重读他的问题,你会发现。@newboyhun人们要求的并不总是他们需要的,你的解决方案也不错,只是不适合这种情况。它导致了OP。
class ObjectStore
{
    private $decoded;
    private $asssocArray;

    public function __construct($jsonEncodedObjects)
    {
        $this->decoded = json_decode($jsonEncodedObjects);
    }

    public function getObject($objectName)
    {
        if(!$this->asssocArray){
            foreach($this->decoded as $object){
                $this->asssocArray[$object->name] = $object;
            }
        }
        return $this->asssocArray[$objectName];
    }
}
$objectStore = new ObjectStore(getJsonEncodedData());

$hashtag = "test-song-poll-03";
$myObject = $objectStore->getObject($hashtag);