18

コールバックに単一の追加引数を渡すにはどうすればよいarray_mapですか?私の例$smsPatternでは、(の現在の要素の後に、2番目の引数として)クロージャーを使用し$featureNamesて関数に渡したいと思います。array_map$getLimit

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

このコードで私は奇妙な警告を受けています:

警告:array_map()[function.array-map]:引数#3は配列である必要があります。

もちろん、理由は、の$getLimitような別の正規表現でクロージャを再利用するためです$smsPattern。ありがとう。

4

2 に答える 2

41

これはまさにクロージャの目的です。

$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));
于 2012-06-03T16:43:09.950 に答える
0

array_map()ドキュメントで概説されているように、配列の後に追加の引数を渡すことができます。キャッチは、引数が配列でなければならないということです。この配列の各値は、処理中の配列内の対応するインデックスとともにコールバックに渡されるため、同じ長さにする必要があります。反復ごとに使用する引数が1つしかない場合は、次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
)
于 2020-02-25T18:43:48.403 に答える