array_filter 有元素修改

array_filter with element modification

我正在尝试从我的用户将定义的字符串创建一个干净的数组。 该字符串可以包含无效的 ID、空格等。我在 array_filter.

的回调函数中使用值对象检查元素
$definedIds = "123,1234,1243, 12434 , asdf"; //from users panel

$validIds = array_map(
    'trim',
    array_filter(
        explode(",", $definedIds),
        function ($i) {
            try {
                new Id(trim($i));
                return true;
            } catch (\Exception $e) {
                return false;
            }
        }
    )
);

这很好用,但我要应用 trim 两次。有没有更好的方法或不同的 PHP 函数,我可以在其中修改元素,然后再将其保存在返回的数组中?

注意:我也可以在 array_filter 的第一个参数中调用 array_map,但无论如何我都会遍历数组两次。

就看你是否在乎性能了。如果这样做,请不要使用 map+filter,而是使用普通的 for 循环并就地操作数组:

$arr = explode(',', $input);

for($i=count($arr)-1; $i>=0; $i--) {
  // make this return trimmed string, or false,
  // and have it trim the input instead of doing
  // that upfront before passing it into the function.
  $v = $arr[$i] = Id.makeValid($arr[$i]);

  // weed out invalid ids
  if ($v === false) {
    array_splice($arr, $i, 1);
  }
}

// at this point, $arr only contains valid, cleaned ids

当然,如果这是无关紧要的代码,那么修剪两次确实不会造成性能差异,但您仍然可以清理它们:

$arr = explode(',', $input);
$arr = array_filter(
  array_map('Id.isValidId', $arr),
  function ($i) {
    return $i !== false;
  }
);  

在这个例子中,我们首先使用那个函数进行映射,所以我们得到一个id数组和false值,然后我们过滤它,这样所有false 被扔掉,而不是先过滤,再映射。

(在这两种情况下,负责检查有效性的代码都在 Id class 中,它要么是 returns 一个清理过的 id,要么是 false

其实你可以用不同的方式来做,但如果我是你,我会这样做。这里我只用了一个trim

<?php
$definedIds = "123,1234,1243, 12434 , asdf"; //from users panel
function my_filter($b){
    if(is_numeric($b)){
        return true;
    }
}
print '<pre>';
$trimmed = array_map('trim',explode(',',$definedIds));
print_r(array_filter($trimmed,my_filter));
print '</pre>';
?>

程序输出:

Array
(
    [0] => 123
    [1] => 1234
    [2] => 1243
    [3] => 12434
)

演示: https://eval.in/997812