如何在PHP中向array_map回调函数传递单个额外参数?

18

我如何向array_map回调函数传递一个额外的参数? 在我的示例中,我想将$smsPattern作为第二个参数(在$featureNames中当前元素之后)传递给使用闭包$getLimitarray_map函数:

$features = $usage->getSubscription()->getUser()->getRoles();

// SMS regular expression in the form of ROLE_SEND_SMS_X
$smsPattern = '/^ROLE_SEND_SMS_(?P<l>\d+)$/i';

// Function to get roles names and X from a role name
$getNames = function($r) { return trim($r->getRole()); };
$getLimit = function($name, $pattern) {
    if(preg_match($pattern, $name, $m)) return $m['l'];
};

// Get roles names and their limits ignoring null values with array_filter
$featuresNames = array_map($getNames, $features);
$smsLimits     = array_filter(array_map($getLimit,  $featureNames, $smsPattern));

使用这段代码会出现一个奇怪的警告:

Warning: array_map() [function.array-map]: Argument #3 should be an array.

当然,原因是由于将 $getLimit 闭包与另一个正则表达式如 $smsPattern 重复使用。谢谢。


为什么不使用array_walk()函数呢?这样你就可以传递一个额外的参数。 - Mark Baker
你在使用 array_filter 做什么? - Emil Vikström
@EmilVikström 移除空值。 - gremo
好的!我甚至不知道array_filter可以在没有回调函数的情况下工作。现在我知道了,并且我也已经将其添加到我的答案中了。 - Emil Vikström
2个回答

42

这正是闭包的精髓所在:

$getLimit = function($name) use ($smsPattern) {
    if(preg_match($smsPattern, $name, $m)) return $m['l'];
};

$smsLimits = array_filter(array_map($getLimit, $features));

如果你想将其泛化到其他模式,将函数创建包装在另一个函数中:

function patternMatcher($pattern) {
    return function($name) use ($pattern) {
        if(preg_match($pattern, $name, $m)) return $m['l'];
    };
}

$getLimit = patternMatcher($smsPattern);
$smsLimits = array_filter(array_map($getLimit, $features));

下面是将其封装为匿名函数:

$patternMatcher = function($pattern) {
    return function($name) use ($pattern) {
        if(preg_match($pattern, $name, $m)) return $m['l'];
    };
};

$smsLimits = array_filter(array_map($patternMatcher($smsPattern), $features));

0

如文档中所述,您可以在数组之后传递其他参数给 array_map()。但是需要注意的是,这个参数必须是一个数组。该数组中的每个值都将与正在处理的数组中相应的索引一起传递到回调函数中,因此您希望它们具有相同的长度。如果您只有一个要在每次迭代中使用的参数,您可以使用 array_fill() 来填充参数数组,如下所示:

$smsLimits = array_map(
    $getLimit,
    $featureNames,
    array_fill(0, count($featureNames), $smsPattern)
);

一个常见的用例是,你可能想从一个 URL 数组中删除单个字符,比如 /
$urls = ['http://example.com/','http://sub.example.com/'];
$urls = array_map('rtrim', $urls, array_fill(0, count($urls), '/'));

这将导致:

Array
(
    [0] => http://example.com
    [1] => http://sub.example.com
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接