$array[0]->id = 'one';
$array[0]->color = 'white';
$array[1]->id = 'two';
$array[1]->color = 'red';
$array[2]->id = 'three';
$array[2]->color = 'blue';
实现像
这样的方法的最快,最有效的方法是什么function findObjectById($ id){}
如果我调用它将返回对象$ array [0]:
$obj = findObjectById('one')
并且如果我通过'四'作为参数将返回false。
答案 0 :(得分:8)
您可以迭代这些对象:
function findObjectById($id){
$array = array( /* your array of objects */ );
foreach ( $array as $element ) {
if ( $id == $element->id ) {
return $element;
}
}
return false;
}
修改强>
更快的方法是让一个数组的键等于对象的id(如果是唯一的);
然后你可以建立你的功能如下:
function findObjectById($id){
$array = array( /* your array of objects with ids as keys */ );
if ( isset( $array[$id] ) ) {
return $array[$id];
}
return false;
}
答案 1 :(得分:3)
好吧,你将不得不循环遍历它们并检查比较ID,除非您的数组已经排序(按ID),在这种情况下,您可以实现搜索算法,如二进制搜索或类似的东西,以使其更快。< / p>
我的建议是首先使用排序算法(二进制排序,插入排序或快速排序)对数组进行排序(如果数组尚未排序)。然后你可以实现一个搜索算法,它应该可以提高性能,我认为这样做会很好。
答案 2 :(得分:3)
这是一个老问题,但对于规范参考,因为它在纯形式中缺失:
uniquePaths
$obj = array_column($array, null, 'id')['one'] ?? false;
是根据问题要求返回 false。它代表不匹配的值,例如例如,您可以将其设为 false
作为替代建议。
从 PHP 7.0 开始就透明了。如果您(仍然)有旧版本,则可以使用它的用户空间实现来替代。
然而 null
也意味着复制整个数组。这可能不需要。
相反,它可以用于索引数组,然后用 array_column
映射:
array_flip
在索引上,搜索问题可能仍然相同,地图只提供原始数组中的索引,因此存在参考系统。
请记住,这可能不是必需的,因为 PHP 具有写时复制功能。因此,可能会减少有意认为的重复。所以这是为了显示一些选项。
另一个选择是遍历整个数组,除非已经找到对象,否则检查匹配。一种方法是使用 $index = array_column($array, 'id');
$map = array_flip($index);
$obj = $array[$map['onex'] ?? null] ?? false;
:
array_reduce
此变体再次具有不匹配的返回 $obj = array_reduce($array, static function ($carry, $item) {
return $carry === false && $item->id === 'one' ? $item : $carry;
}, false);
要求。
false
更直接:
null
然后可以使用 $obj = array_reduce($array, static function ($carry, $item) {
return $carry ?? ($item->id === 'one' ? $item : $carry);
}, null);
添加不同的不匹配要求。
在自己的函数内完全暴露于 $obj = ...) ?? false;
甚至有利于直接退出匹配:
foreach
这实际上是 original answer by hsz,它显示了它的应用范围。
答案 3 :(得分:2)
具有数据结构性能的东西不仅仅是如何获得,而且主要是如何存储我的数据。
如果您可以自由设计数组,请使用关联数组:
$array['one']->id = 'one';
$array['one']->color = 'white';
$array['two']->id = 'two';
$array['two']->color = 'red';
$array['three']->id = 'three';
$array['three']->color = 'blue';
然后找到最便宜的:$ one = $ array ['one];
<强>更新强>
如果无法修改数组构造,可以创建一个单独的数组,将数据映射到索引。以这种方式查找对象不会花费任何时间:
$map['one'] = 0;
$map['two'] = 1;
$map['three'] = 2;
...
getObjectById()
然后首先查找原始数组中id的索引,然后返回正确的对象:
$index = $map[$id];
return $array[$index];
答案 4 :(得分:2)
这是我绝对喜欢的算法,可以非常快速地在非常大的数组中快速找到所需的内容。这是我在PHP代码中创建并广泛使用的Binary Search Algorithm实现。它毫不费力地击败了直接迭代的搜索例程。您可以根据需要进行多种选择,但基本算法保持不变。
要使用此变量(此变体),必须按要查找的索引对数组进行从最低到最高的排序。
function quick_find(&$array, $property, $value_to_find, &$first_index) {
$l = 0;
$r = count($array) - 1;
$m = 0;
while ($l <= $r) {
$m = floor(($l + $r) / 2);
if ($array[$m]->{$property} < $value_to_find) {
$l = $m + 1;
} else if ($array[$m]->{$property} > $value_to_find) {
$r = $m - 1;
} else {
$first_index = $m;
return $array[$m];
}
}
return FALSE;
}
并进行测试:
/* Define a class to put into our array of objects */
class test_object {
public $index;
public $whatever_you_want;
public function __construct( $index_to_assign ) {
$this->index = $index_to_assign;
$this->whatever_you_want = rand(1, 10000000);
}
}
/* Initialize an empty array we will fill with our objects */
$my_array = array();
/* Get a random starting index to simulate data (possibly loaded from a database) */
$my_index = rand(1256, 30000);
/* Say we are needing to locate the record with this index */
$index_to_locate = $my_index + rand(200, 30234);
/*
* Fill "$my_array()" with ONE MILLION objects of type "test_object"
*
* 1,000,000 objects may take a little bit to generate. If you don't
* feel patient, you may lower the number!
*
*/
for ($i = 0; $i < 1000000; $i++) {
$searchable_object = new test_object($my_index); // Create the object
array_push($my_array, $searchable_object); // Add it to the "$my_array" array
$my_index++; /* Increment our unique index */
}
echo "Searching array of ".count($my_array)." objects for index: " . $index_to_locate ."\n\n";
$index_found = -1; // Variable into which the array-index at which our object was found will be placed upon return of the function.
$object = quick_find($my_array, "index", $index_to_locate, $index_found);
if ($object == NULL) {
echo "Index $index_to_locate was not contained in the array.\n";
} else {
echo "Object found at index $index_found!\n";
print_r($object);
}
echo "\n\n";
现在,一些注意事项:
您 MAY 使用它来查找非唯一索引;数组仍必须按升序排序。然后,当找到与您的条件匹配的元素时,您必须向后移动数组以找到第一个元素,或者向前走以找到最后一个元素。它将为您的搜索添加一些“跃点”,但仍可能比迭代大型数组更快。
对于STRING索引,您可以将quick_find()中的算术比较(即“>”和“ <”)更改为PHP函数“ strcasecmp()”。只要确保STRING索引的排序方式相同(对于示例实现):按字母顺序和升序。
如果您想拥有一个可以搜索以 EITHER 升序 OR 降序排列的对象数组的版本:
function quick_find_a(&$array, $property, $value_to_find, &$first_index) {
$l = 0;
$r = count($array) - 1;
$m = 0;
while ($l <= $r) {
$m = floor(($l + $r) / 2);
if ($array[$m]->{$property} < $value_to_find) {
$l = $m + 1;
} else if ($array[$m]->{$property} > $value_to_find) {
$r = $m - 1;
} else {
$first_index = $m;
return $array[$m];
}
}
return FALSE;
}
function quick_find_d(&$array, $property, $value_to_find, &$first_index) {
$l = 0;
$r = count($array) - 1;
$m = 0;
while ($l <= $r) {
$m = floor(($l + $r) / 2);
if ($value_to_find > $array[$m]->{$property}) {
$r = $m - 1;
} else if ($value_to_find < $array[$m]->{$property}) {
$l = $m + 1;
} else {
$first_index = $m;
return $array[$m];
}
}
return FALSE;
}
function quick_find(&$array, $property, $value_to_find, &$first_index) {
if ($array[0]->{$property} < $array[count($array)-1]->{$property}) {
return quick_find_a($array, $property, $value_to_find, $first_index);
} else {
return quick_find_d($array, $property, $value_to_find, $first_index);
}
}
答案 5 :(得分:1)
我喜欢在这些情况下做的事情是创建一个引用数组,从而避免重新复制对象,但有权使用对象本身的引用。
$array['one']->id = 'one';
$array['one']->color = 'white';
$array['two']->id = 'two';
$array['two']->color = 'red';
$array['three']->id = 'three';
$array['three']->color = 'blue';
然后我们可以创建一个简单的引用数组:
$ref = array();
foreach ( $array as $row )
$ref[$row->id] = &$array[$row->id];
现在我们可以简单地测试数组中是否存在实例,如果需要,甚至可以像原始对象一样使用它:
if ( isset( $ref['one'] ) )
echo $ref['one']->color;
会输出:
white
如果有问题的id不存在,则isset()将返回false,因此不需要反复遍历原始对象寻找值......我们只使用PHP的isset()函数并避免使用一个单独的功能。
请注意在使用您想要的参考时使用“&amp;”使用原始数组而不是迭代器,因此使用&amp; $ row不会给你你想要的东西。
答案 6 :(得分:1)
您可以像这样使用php的array_search函数
$key=array_search("one", array_column(json_decode(json_encode($array),TRUE), 'color'));
var_dump($array[$key]);
答案 7 :(得分:0)
这是我使用的。循环遍历对象数组的可重用函数。第二个允许您直接从所有匹配中检索单个对象(第一个匹配条件)。
function get_objects_where($match, $objects) {
if ($match == '' || !is_array($match)) return array ();
$wanted_objects = array ();
foreach ($objects as $object) {
$wanted = false;
foreach ($match as $k => $v) {
if (is_object($object) && isset($object->$k) && $object->$k == $v) {
$wanted = true;
} else {
$wanted = false;
break;
};
};
if ($wanted) $wanted_objects[] = $object;
};
return $wanted_objects;
};
function get_object_where($match, $objects) {
if ($match == '' || !is_array($match)) return (object) array ();
$wanted_objects = get_objects_where($match, $objects);
return count($wanted_objects) > 0 ? $wanted_objects[0] : (object) array ();
};
答案 8 :(得分:0)
这绝对没有效率,O(N)。但看起来很性感:
$result = array_reduce($array, function ($found, $obj) use ($id) {
return $obj['id'] == $id ? $obj : $found;
}, null);
附录: 我看到 hakre 已经发布了类似的内容。