Существует ли эквивалент функции Array.prototype.some() на PHP?

Вопрос или проблема

В JavaScript мы можем сделать следующее:

function isBiggerThan10(element, index, array) {
  return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10);  // ложь
[12, 5, 8, 1, 4].some(isBiggerThan10); // истина

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some

Есть ли аналог функции some() в PHP?

Она не входит в стандартную библиотеку, но их легко создать. Это использует имена SRFI-1 any и every, но их можно переименовать в some и all:

function array_any(array $array, callable $fn) {
    foreach ($array as $value) {
        if($fn($value)) {
            return true;
        }
    }
    return false;
}

function array_every(array $array, callable $fn) {
    foreach ($array as $value) {
        if(!$fn($value)) {
            return false;
        }
    }
    return true;
}

Нет, в стандартной библиотеке PHP нет эквивалента короткого замыкания. Существует множество решений без короткого замыкания, среди которых array_reduce подойдет лучше всего:

var_dump(array_reduce([2, 5, 8, 1, 4], function ($isBigger, $num) {
    return $isBigger || $num > 10;
}));

Возможно, стоит реализовать свои собственные функции some/any/all или использовать библиотеку, которая предоставляет коллекцию примитива функционального программирования, например https://github.com/lstrojny/functional-php.

Редактировать: PHP >= 8.4

Теперь в PHP 8.4 вы можете использовать array_any

$some = array_any($data, fn ($item) => $item > 10);

Так же, как и ее эквивалент для Array.every() в PHP 8.4, вы можете использовать array_all

$every = array_all($data, fn ($item) => $item > 10);

https://php.watch/versions/8.4/array_find-array_find_key-array_any-array_all

PHP < 8.4

Используйте array_filter и предоставьте колбек. Оберните это в другую функцию, чтобы посчитать, есть ли какие-либо результаты

function array_some(array $data, callable $callback) {
    $result = array_filter($data, $callback);
    return count($result) > 0;
}

$myarray = [2, 5, 8, 12, 4];
array_some($myarray, function($value) {
    return $value > 10;
}); // истина

Есть array_filter(), который возвращает подмножество данного массива на основе возвращаемого значения данного колбека. Если подмножество пусто, то это будет эквивалентно тому, что Some() возвращает ложь, а если не пусто, то это будет соответствовать тому, что Some() возвращает истину.

$unfiltered = [1, 11, 2, 22, 3, 33, 4, 44, 5, 55];
$filtered = array_filter ($unfiltered, function ($elem){
    return $elem > 10;
});

print_r ($unfiltered);
print_r ($filtered);
var_dump (empty ($filtered));

Этот подход не использует короткое замыкание, однако производительность будет обратно пропорциональна размеру массива. Тем не менее, это не должно иметь значения в реальной жизни, поскольку массив все равно должен стать довольно большим, или array_filter вызывается много раз, прежде чем вы заметите влияние на производительность.

Если производительность является главным приоритетом, вам придется сами перебрать массив и выйти из цикла, как только найдете совпадение.

$biggerThanTen = false;
foreach ($unfiltered as $elem)
{
    if ($elem > 10)
    {
        $biggerThanTen = true;
        break;
    }
}

function array_some(array $array, callable $callback) {

        $i = 0;
        $n = count($array);

        while($i<$n && !$callback($array[$i])) {
            $i++;
        }

        return $array[$i] ?? null;
}

Функция возвращает null, если не найден ни один элемент, удовлетворяющий условию функции “callback”.

Если будет найден элемент, удовлетворяющий условию, она вернет первый найденный.

Функция “callback”, переданная в качестве параметра, должна возвращать true или false в зависимости от того, удовлетворяет ли элемент условию.

Вот функция PHP, которая работает как функция JavaScript Array.some().

Я думаю, что код говорит сам за себя, но если у вас есть какие-либо вопросы, не стесняйтесь спрашивать меня.

// Функция Array.some(), подобная JavaScript
$array_some = function($an_array, $callback_function) {
    $is_data_found = false;
    foreach ($an_array as $an_array_index => $array_item) {
        $is_data_found = $callback_function($array_item, $an_array_index, $an_array);
        if ($is_data_found) return $is_data_found;
    }
    return $is_data_found;
};

Использование в обычном массиве:

$numbers = [12, 34, 27, 23, 65, 93, 36, 87, 4, 254];

$is_any_number_less_than500 = $array_some($numbers, fn($number) => $number < 500) === false ? 'ложь' : 'истина';
echo("<pre>есть ли число < 500: $is_any_number_less_than500</pre><br />");
// есть ли число < 500: истина

$is_any_number_more_than500 = $array_some($numbers, fn($number) => $number > 500) === false ? 'ложь' : 'истина';
echo("<pre>есть ли число > 500: $is_any_number_more_than500</pre><br /><br />");
// есть ли число > 500: ложь

Использование в ассоциативном массиве:
(Массив объектов, подобный JavaScript / JSON, подобный JavaScript)

$products = [
    ['id' => 'id_1', 'price' => 30],
    ['id' => 'id_2', 'price' => 233],
    ['id' => 'id_3', 'price' => 5],
    ['id' => 'id_4', 'price' => 499]
];

$is_any_product_price_less_than500 = $array_some($products, fn($product) => @$product['price'] < 500) === false ? 'ложь' : 'истина';
echo("<pre>есть ли цена товара < 500: $is_any_product_price_less_than500</pre><br />");
// есть ли цена товара < 500: истина

$is_any_product_price_more_than500 = $array_some($products, fn($product) => @$product['price'] > 500) === false ? 'ложь' : 'истина';
echo("<pre>есть ли цена товара > 500: $is_any_product_price_more_than500</pre><br /><br />");
// есть ли цена товара > 500: истина

Использование данных OP:

$is_any_number_bigger_than10 = $array_some([2, 5, 8, 1, 4], fn($number) => $number > 10) === false ? 'ложь' : 'истина';
echo("<pre>есть ли число > 10: $is_any_number_bigger_than10</pre><br />");
// есть ли число > 10: ложь

$is_any_number_bigger_than10 = $array_some([12, 5, 8, 1, 4], fn($number) => $number > 10) === false ? 'ложь' : 'истина';
echo("<pre>есть ли число > 10: $is_any_number_bigger_than10</pre><br /><br />");
// есть ли число > 10: истина

Ответ или решение

В PHP нет прямого аналога функции Array.prototype.some() из JavaScript, однако, вы можете легко создать свою собственную функцию, которая будет выполнять ту же задачу.

Функция some() в JavaScript проверяет, удовлетворяет ли хотя бы один элемент массива условию, заданному в переданной функции-коллбэке, и возвращает true или false в зависимости от результата. А вот решения для PHP можно реализовать несколькими способами.

Решение для PHP < 8.4

Если вы используете PHP версии ниже 8.4, вы можете определить следующую функцию array_some(), чтобы добиться похожего поведения:

function array_some(array $array, callable $callback) {
    foreach ($array as $item) {
        if ($callback($item)) {
            return true; // Если коллбэк возвращает true, возращаем true
        }
    }
    return false; // Если ни один элемент не прошел, возвращаем false
}

// Пример использования
$numbers1 = [2, 5, 8, 1, 4];
$result1 = array_some($numbers1, fn($number) => $number > 10); // false

$numbers2 = [12, 5, 8, 1, 4];
$result2 = array_some($numbers2, fn($number) => $number > 10); // true

var_dump($result1); // bool(false)
var_dump($result2); // bool(true)

Решение для PHP >= 8.4

С выходом версии PHP 8.4 в стандартную библиотеку были добавлены функции array_any() и array_all(), которые обеспечивают прямой аналог JavaScript функции some():

// Пример использования функции array_any в PHP 8.4 и выше
$data = [2, 5, 8, 1, 4];
$some = array_any($data, fn($item) => $item > 10); // false

$data2 = [12, 5, 8, 1, 4];
$some2 = array_any($data2, fn($item) => $item > 10); // true

var_dump($some); // bool(false)
var_dump($some2); // bool(true)

Использование array_filter

Также можно использовать функцию array_filter, чтобы отфильтровать элементы массива по условию:

function array_some_via_filter(array $data, callable $callback) {
    $filtered = array_filter($data, $callback); // Фильтруем массив
    return count($filtered) > 0; // Если имеются элементы, удовлетворяющие условию, возвращаем true
}

$result3 = array_some_via_filter([2, 5, 8, 1, 4], fn($number) => $number > 10); // false
$result4 = array_some_via_filter([12, 5, 8, 1, 4], fn($number) => $number > 10); // true

var_dump($result3); // bool(false)
var_dump($result4); // bool(true)

Заключение

В зависимости от версии вашего PHP и ваших предпочтений, вы можете использовать один из предложенных способов для реализации функциональности, аналогичной Array.prototype.some() из JavaScript. В PHP 8.4 и выше возможности стандартной библиотеки значительно расширены, что упрощает выполнение таких задач без необходимости писать дополнительные функции.

Оцените материал
Добавить комментарий

Капча загружается...