Elegant way to search an PHP array using a user-defined function

后端 未结 6 1421
感情败类
感情败类 2020-12-06 03:58

Basically, I want to be able to get the functionality of C++\'s find_if(), Smalltalk\'s detect: etc.:

// would return the element o         


        
相关标签:
6条回答
  • 2020-12-06 04:32

    You can write your own function ;)

    function callback_search ($array, $callback) { // name may vary
        return array_filter($array, $callback);
    }
    

    This maybe seems useless, but it increases semantics and can increase readability

    0 讨论(0)
  • 2020-12-06 04:33

    To pull the first one from the array, or return false:

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

    More info on current() here.

    0 讨论(0)
  • 2020-12-06 04:40

    You can write such a function yourself, although it is little more than a loop.

    For instance, this function allows you to pass a callback function. The callback can either return 0 or a value. The callback I specify returns the integer if it is > 10. The function stops when the callback returns a non null value.

    function check_in_array(array $array, $callback)
    {
      foreach($array as $item)
      {
        $value = call_user_func($callback, $item);
        if ($value !== null)
          return $value;
      }
    }
    
    $a = array(1, 2, 3, 6, 9, 11, 15);
    echo check_in_array($a, function($i){ return ($i > 10?$i:null); });
    
    0 讨论(0)
  • 2020-12-06 04:42

    Use \iter\search() from nikic's iter library of primitive iteration functions. It has the added benefit that it operates on both arrays and Traversable collections.

    $foundItem = \iter\search(function ($item) {
        return $item > 10;
    }, range(1, 20));
    
    if ($foundItem !== null) {
        echo $foundItem; // 11
    }
    
    0 讨论(0)
  • 2020-12-06 04:44

    The original array_search returns the key of the matched value, and not the value itself (this might be useful if you're will to change the original array later).

    try this function (it also works will associatives arrays)

    function array_search_func(array $arr, $func)
    {
        foreach ($arr as $key => $v)
            if ($func($v))
                return $key;
    
        return false;
    }
    
    0 讨论(0)
  • 2020-12-06 04:54

    Here's a basic solution

    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
    

    In the event $f($x) returns true, the loop short circuits and $x is immediately returned. Compared to array_filter, this is better for our use case because array_find does not have to continue iterating after the first positive match has been found.

    In the event the callback never returns true, a value of null is returned.


    Note, I used call_user_func($f, $x) instead of just calling $f($x). This is appropriate here because it allows you to use any compatible callable

    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'
    

    Of course it works for more complex data structures too

    $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
    // )
    

    If you're using PHP 7, add some type hints

    function array_find(array $xs, callable $f) { ...
    
    0 讨论(0)
提交回复
热议问题