使用用户定义的函数搜索 PHP 数组的优雅方式

2022-08-30 09:36:43

基本上,我希望能够获得C++,Smalltalk等的功能:find_if()detect:

// would return the element or null
check_in_array($myArray, function($element) { return $elemnt->foo() > 10; });

但我不知道有任何PHP函数可以做到这一点。我想出了一个“近似值”:

$check = array_filter($myArray, function($element) { ... });
if ($check) 
    //...

这样做的缺点是代码的目的并不明确。此外,即使找到元素,它也不会停止迭代数组,尽管这更像是一个挑剔(如果数据集足够大,会导致问题,线性搜索无论如何都不会是答案)


答案 1

要从数组中拉取第一个,或返回:false

current(array_filter($myArray, function($element) { ... }))

有关 current() 的更多信息,请单击此处


答案 2

这是一个基本解决方案

function array_find($xs, $f) {
  foreach ($xs as $x) {
    if (call_user_func($f, $x) === true)
      return $x;
  }
  return null;
}

array_find([1,2,3,4,5,6], function($x) { return $x > 4; });  // 5
array_find([1,2,3,4,5,6], function($x) { return $x > 10; }); // null

在事件返回时,循环短路并立即返回。与 相比,这更适合我们的用例,因为在找到第一个正匹配项后不必继续迭代。$f($x)true$xarray_filterarray_find

如果回调从不返回 true,则返回值 。null


请注意,我使用的不仅仅是调用.这在这里是合适的,因为它允许您使用任何兼容的可调用call_user_func($f, $x)$f($x)

Class Foo {
  static private $data = 'z';
  static public function match($x) {
    return $x === self::$data;
  }
}

array_find(['x', 'y', 'z', 1, 2, 3], ['Foo', 'match']); // 'z'

当然,它也适用于更复杂的数据结构。

$data = [
  (object) ['id' => 1, 'value' => 'x'],
  (object) ['id' => 2, 'value' => 'y'],
  (object) ['id' => 3, 'value' => 'z']
];

array_find($data, function($x) { return $x->id === 3; });
// stdClass Object (
//     [id] => 3
//     [value] => z
// )

如果您使用的是 PHP 7,请添加一些类型提示

function array_find(array $xs, callable $f) { ...

推荐