我目前正在尝试将一些 JavaScript 移植到 PHP 上。但是,我似乎找不到 PHP 中与 JavaScript 的 array.every()
函数等价的函数。我找到了 PHP 的 each()
函数,但它似乎并不完全符合我的需求。
我目前正在尝试将一些 JavaScript 移植到 PHP 上。但是,我似乎找不到 PHP 中与 JavaScript 的 array.every()
函数等价的函数。我找到了 PHP 的 each()
函数,但它似乎并不完全符合我的需求。
使用for循环并进行提前返回。
PHP没有原生函数能够像Javascript的array#every一样执行相同的功能。
every
或Python中的all
)的语义。映射和归约是不正确的,因为它们会访问每个元素,而不管它们的真值如何。some
或any
。<?php
function array_every(array $arr, callable $predicate) {
foreach ($arr as $e) {
if (!call_user_func($predicate, $e)) {
return false;
}
}
return true;
}
function array_any(array $arr, callable $predicate) {
return !array_every($arr, fn($e) => !call_user_func($predicate, $e));
}
// sample predicate
function is_even(int $e) {
return $e % 2 === 0;
}
var_dump(array_every([0, 1, 2, 3], "is_even")); // => bool(false)
var_dump(array_every([0, 2], "is_even")); // => bool(true)
var_dump(array_any([1, 2], "is_even")); // => bool(true)
var_dump(array_any([1, 3], "is_even")); // => bool(false)
foreach()
:function allEven(array $values)
{
foreach ($values as $value) {
if (1 === $value % 2) {
return false;
}
}
return true;
}
$data = [
1,
42,
9000,
];
$allEven = allEven($data);
参考资料:
注意:使用foreach
比使用array_reduce()
更好,因为一旦找到不符合规定的值,评估就会停止。
array_reduce
文档--那个函数并不适合这个目的(正如你所说!),而且你在代码中也没有使用它(正确!)。 - ggorlen我首先写下了这些代码:
function array_every(callable $callback, array $array) {
$matches = [];
foreach ($array as $item) {
if ($callback($item)) {
$matches[] = true;
} else {
$matches[] = false;
}
}
if (in_array(false, $matches)) {
return false;
}
return true;
}
然后编写了其迷你版本:
function array_every(callable $callback, array $array) {
foreach ($array as $item) {
if (!$callback($item)) return false;
}
return true;
}
用法:
$array = [1, 2, 3];
$result = array_every(function($item) {
return $item == 3; // Check if all items are 3 or not (This part is like JS)
}, $array);
echo $result; // Returns false, but returns true if $array = [3, 3, 3]
所以两个版本都很好
你已经得到了答案!:)
Php array_every函数
function array_every($array,$callback)
{
return !in_array(false, array_map($callback,$array));
}
array_every([1,2,3],function($n){
return $n>0;
});
array_reduce
这个函数很好用(我经常使用它),但你应该把它当成“备选方案”。因为它每次都需要扫描整个数组,而 Array#every
函数只要有一个回调函数返回假值就会立即停止执行。 - Josh from Qariboufunction array_every(array $array, callable $fn) {
return (bool)array_product(array_map($fn, $array));
}
在线查看: https://3v4l.org/1D1Ao
这只是一个概念验证,尚未进行优化。对于生产环境,我会使用 foreach
来在第一个未通过测试的项目上返回 false
。
我准备了这个解决方案,尽可能接近JavaScript的Array.prototype.every()
。
描述:
array_every()
方法测试提供的函数实现的数组中的所有元素是否都通过测试。它返回一个布尔值。
array_every()
方法对数组中的每个元素执行提供的$callback
函数,直到找到其中一个元素使$callback
返回假值。如果找到这样的元素,则array_every()
方法立即返回false。否则,如果$callback
对于所有元素都返回真值,则返回true。
注意:在空数组上调用此方法将对任何条件返回true!
array_every()
方法不会改变其被调用的数组。
array_every(array $array, string|callable $callback, null|string|object $thisArg = null): bool
$array
要迭代的数组。
$callback
一个回调函数,用于测试每个元素,它有四个参数:
$value - 正在处理的元素的当前值。
$key (可选) - 正在处理的元素的当前键。
$index (可选) - 正在处理的元素在数组中的索引。
$array (可选) - 正在遍历的数组。
$thisArg (可选)
在执行$callback
函数时使用的$this
值。
如果$callback
函数对每个数组元素返回一个 truthy 值,则返回true
。否则,返回false
。
function array_every(array $array, string|callable $callback, null|string|object $thisArg = null): bool
{
$index = 0;
foreach ($array as $key => $value) {
$condition = false;
if (is_null($thisArg)) {
$condition = call_user_func_array($callback, [$value, $key, $index, $array]);
} else if (is_object($thisArg) || (is_string($thisArg) && class_exists($thisArg))) {
$condition = call_user_func_array([$thisArg, $callback], [$value, $key, $index, $array]);
} else if (is_string($thisArg) && !class_exists($thisArg)) {
throw new TypeError("Class '$thisArg' not found");
}
if (!$condition)
return false;
$index++;
}
return true;
}
$isEven = fn($v) => ($v % 2 === 0);
var_export(array_every([2, 8, 16, 36], $isEven)); // true
如果向array_every()
方法提供了$thisArg
参数,则它将用作$callback
的$this
值。否则,将使用值null
作为其$this
值。
class Helper
{
public function isOlderThan18(int $value): bool
{
return $value > 18;
}
public static function isVowel(string $character): bool
{
return in_array($character, ['a', 'e', 'i', 'o', 'u']);
}
}
如果需要声明在命名空间下的类,您可以在$thisArg
参数中传递完整的限定类名。
var_export(array_every(["a", "u", "e"], "isVowel", "Helper")); // true
$thisArg
参数也可以是一个对象。
var_export(array_every(["Peter" => "35", "Ben" => "16", "Joe" => "43"], "isOlderThan18", (new Helper))); // false
这里还有另一个选项(实际上,许多数组函数可以相似地使用):
$bool = !empty(array_filter(['my', 'test', 'array'], function ($item) {
return $item === 'array';
}));
或者针对PHP7.4+,使用箭头函数:
$bool = !empty(array_filter(['my', 'test', 'array'], fn($item) => $item === 'array'));
...看起来有点像JS:
let bool = ['my', 'test', 'array'].every(item => item === 'array'));
而且还分裂了:
function array_every(array $array, callable $callback) {
return !empty(array_filter($array, $callback));
}
$myArr = ['my', 'test', 'array'];
$myTest = fn($item) => $item === 'array'; // PHP7.4+
$bool = array_every($myArr, $myTest);
同样,可以使用几个数组函数来返回一个空的或填充的数组。虽然正如上面有人提到的那样,实际的JS [].every
会在得到一个true
返回时立即停止,如果你需要迭代一个大数组,这可以节省大量时间。我遇到了这个问题,寻找一种快速的函数式编程风格的代码来迭代仅三个数组项。
protected function checkIsNumber($arrayNumbers = []) {
$ga = NULL;
foreach($arrayNumbers as $value) {
if(is_null($ga)) {
$ga = is_numeric(trim($value));
} else {
$ga = $ga === is_numeric(trim($value));
}
}
return $ga;
}
every
函数是否检查每个元素是否满足谓词?有时它被称为all
。 - Carcigenicate