programing

사용자 정의 함수를 사용하여 PHP 배열을 검색하는 우아한 방법

muds 2023. 7. 25. 21:25
반응형

사용자 정의 함수를 사용하여 PHP 배열을 검색하는 우아한 방법

기본적으로, 저는 C++의 기능을 얻을 수 있기를 원합니다.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) 
    //...

이것의 단점은 코드의 목적이 즉시 명확하지 않다는 것입니다.또한 요소가 발견된 경우에도 어레이에 대한 반복이 멈추지 않습니다. 이는 트릭에 가깝습니다(데이터 세트가 문제를 일으킬 정도로 크면 선형 검색이 답이 되지 않습니다).

배열에서 첫 번째 항목을 가져오거나 반환하려면false:

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

현재()에 대한 자세한 내용은 여기를 참조하십시오.

기본적인 해결책은 다음과 같습니다.

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루프 단락 및$x즉시 반환됩니다.와 비교하여array_filter이것은 우리의 사용 사례에 더 낫습니다. 왜냐하면array_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) { ...

원본array_search값 자체가 아닌 일치된 값의 키를 반환합니다(나중에 원래 배열을 변경하려는 경우 유용할 수 있음).

이 기능을 사용해 보십시오(Will Associates 배열도 작동합니다).

function array_search_func(array $arr, $func)
{
    foreach ($arr as $key => $v)
        if ($func($v))
            return $key;

    return false;
}

Laravel's에서 뽑은Illuminate\Collections\Arr::first방법:

if (!function_exists('array_first')) {
    /**
     * Return the first element in an array passing a given truth test.
     *
     * @param  iterable  $array
     * @param  callable|null  $callback
     * @param  mixed  $default
     * @return mixed
     */
    function array_first($array, callable $callback = null, $default = null)
    {
        if (is_null($callback)) {
            if (empty($array)) {
                return $default;
            }

            foreach ($array as $item) {
                return $item;
            }
        }

        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return $value;
            }
        }

        return $default;
    }
}

꽤 괜찮은 것 같아요.또한 다음과 같은 기능도 있습니다.Illuminate\Collections\Arr::last방법, 하지만 어레이를 반대로 하고 단지 호출하기 때문에 아마도 그렇게 최적화되지 않았을 것입니다.first방법.하지만, 그것은 일을 끝냅니다.

if (!function_exists('array_last')) {
    /**
     * Return the last element in an array passing a given truth test.
     *
     * @param  array  $array
     * @param  callable|null  $callback
     * @param  mixed  $default
     * @return mixed
     */
    function array_last($array, callable $callback = null, $default = null)
    {
        if (is_null($callback)) {
            return empty($array) ? $default : end($array);
        }

        return array_first(array_reverse($array, true), $callback, $default);
    }
}

설명:개체 배열이 있는 경우 해당 달콤한 IDE 자동 완성에 대한 콜백 인수 유형을 지정할 수 있습니다.

$john = array_first($users, function(User $user) {
    return $user->name === 'John';
});

// Works with pretty much anything.

$activeUsers = array_filter($users, function(User $user) {
    return $user->isActive;
});

// Class example:
class User {
    public string $name;
    public bool $isActive;
    //...
}

외부 범위의 변수를 사용하려면 다음을 사용할 수 있습니다.use(&$var)이와 같은 구문

foreach($values as $key => $value) {
  array_find($conditionsRecords, function($row) use(&$key) {
    $keyToFind = $key;
    return $keyToFind;
  })
}

사용하다\iter\search()Nikic의 기본 반복 함수의 반복 라이브러리에서.스토리지와 스토리지 모두에서 작동한다는 추가적인 이점이 있습니다. Traversable소장품

$foundItem = \iter\search(function ($item) {
    return $item > 10;
}, range(1, 20));

if ($foundItem !== null) {
    echo $foundItem; // 11
}

이러한 함수는 루프에 불과하지만 직접 작성할 수 있습니다.

예를 들어, 이 함수를 사용하면 콜백 함수를 전달할 수 있습니다.콜백은 0 또는 값을 반환할 수 있습니다.지정한 콜백이 10보다 클 경우 정수를 반환합니다.콜백이 null이 아닌 값을 반환하면 함수가 중지됩니다.

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); });

자신의 함수를 작성할 수 있습니다 ;)

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

이것은 쓸모 없어 보일 수 있지만 의미론을 증가시키고 가독성을 증가시킬 수 있습니다.

언급URL : https://stackoverflow.com/questions/14224812/elegant-way-to-search-an-php-array-using-a-user-defined-function

반응형