我有一个包含对象的数组。我想获取名为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);
}
答案 0 :(得分:1)
您可以使用array_filter。
$myobjects = array_filter($objects, function($e) use($hashtag) {
return strcmp($e->name, "test-song-poll-03") == 0;
});
由于匿名功能,这只适用于PHP> = 5.3
如果您的版本较旧,则可以使用自己的功能。
答案 1 :(得分:1)
您从json格式的API获取数据的事实并不意味着您必须以您给出的格式保留它。有几种策略比您接受的答案更有效。
当前选择的答案的问题是,每次使用它时,它将迭代整个数据集,即使在第一次迭代中找到匹配项也是如此。我不知道你的数据集有多大,但我认为它很重要,否则你不会问这个问题。
我也不知道你想要访问数据集的次数,你可能也不知道,但我认为它足以让你思考,或者你不会再这样做了。问这个问题。
让我们假设你有一个由1000个stdClass
个对象组成的数据集,并且你要求每个对象一次,所以你可以访问它1000次。
现在' array_filter()'建议你的方法必须每次访问所有1000个元素(它是O(n)),总共1,000,000次迭代。
//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";
第一个想到的选择是一个普通的旧foreach()
循环,这也是O(n),但是一旦找到匹配就可以将循环写入保释。因此,假设我们一旦访问500,500次迭代就访问了数组的每个元素,节省了大约50%。这可能适用于现实世界,也可能不适用,你将是最好的判断。
//Access every element once using foreach(){}
$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 = getObjectWithForeach($name, $objectArray);
}
$end = microtime(true);
$taken = $end - $start;
echo $iterations . " iterations using foreach(){} 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";
以下是我测试代码的其余部分: -
//=================================================================
function getObjectWithArray_Filter($objectName, array $objectArray){
$myobjects = array_filter($objectArray, function($e) use($objectName) {
$e->accessed ++;
return strcmp($e->name, $objectName) == 0;
});
$iterations = 0;
foreach($objectArray as $object){
$iterations += $object->accessed;
}
return $iterations;
}
function getObjectWithForeach($objectName, array $objectArray){
$iterations = 0;
$found = false;
$count = 0;
while(!$found){
$objectArray[$count]->accessed ++;
if($objectArray[$count]->name === $objectName){
$found = true;
}
$count ++;
}
foreach($objectArray as $object){
$iterations += $object->accessed;
}
return $iterations;
}
function getObjectFromAssociativeArray($objectName, array $objectArray){
$iterations = 0;
if($objectName === $objectArray[$objectName]->name){
$objectArray[$objectName]->accessed ++;
}
foreach($objectArray as $object){
$iterations += $object->accessed;
}
return $iterations;
}
<强> TL;博士强>
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);