PHP:array_map関数でインデックスを取得できますか?


83

私は次のようにphpでマップを使用しています:

function func($v) {
    return $v * 2;
}

$values = array(4, 6, 3);
$mapped = array_map(func, $values);
var_dump($mapped);

関数内の値のインデックスを取得することは可能ですか?

また、インデックスが必要なコードを書いている場合、マップの代わりにforループを使用する必要がありますか?

回答:


209

確かに、の助けを借りて、あなたはできる array_keys():

function func($v, $k)
{
    // key is now $k
    return $v * 2;
}

$values = array(4, 6, 3);
$mapped = array_map('func', $values, array_keys($values));
var_dump($mapped);

20
かっこいい答えです。array_map()pedメソッドに追加のパラメーターを渡すことができることに気づいていませんでした。毎日新しいことを学びましょう!
GordonM 2011年

1
@Gordonええarray_map()、任意の数の引数を指定できます:)
Aron Rotteveel 2011年

13
PHPは、によって返されるキーarray_keysが元の配列と同じ順序のままであることを保証しないため、これは非常に危険なアプローチです。したがって、キーを間違った値にマッピングしてしまう可能性があります。安全なアプローチはarray_keys、の2番目の引数としてのみ使用array_mapし、useステートメントを使用して配列をクロージャに渡すことです。
user487772 2015

12
PHPに、コールバックの2番目のパラメーターとして各要素のキーを提供するmap関数がない理由を率直に理解していません。
インフルエンザ

1
@flu PHPは、理由もなく悪い言葉の称号を獲得しませんでした。
xZero

9

匿名配列に無名関数をマッピングする場合、キーにアクセスする方法はありません。

array_map(
    function($val) use ($foo) { /* ... */ },
    array(key1 => val1,
          key2 => val2,
          /* ... */));

array_reduceもキーにアクセスできません。array_walkはキーにアクセスできますが、配列は参照によって渡されるため、間接層が必要です。

いくつかの解決策は次のとおりです。

ペアの配列

元の配列を変更しているので、これは悪いことです。さらに、ボイラープレートの「array()」呼び出しは、配列の長さに比例して増加します。

array_map(
    function($pair) use ($foo) {
        list($key, $val) = $pair;
        /* ... */
    },
    array(array(key1, val1),
          array(key2, val2),
          /* ... */));

一時変数

元の配列を操作しており、ボイラープレートは一定ですが、既存の変数を簡単に壊すことができます。

$i_hope_this_does_not_conflict = array(key1 => val1,
                                       key2 => val2,
                                       /* ... */);
array_map(
    function($key, $val) use ($foo) { /* ... */ },
    array_keys($i_hope_this_does_not_conflict),
    $i_hope_this_does_not_conflict);
unset($i_hope_this_does_not_conflict);

ワンショット機能

関数スコープを使用して既存の名前が壊れるのを防ぐことができますが、「使用」のレイヤーを追加する必要があります。

call_user_func(
    function($arr) use ($foo) {
        return array_map(function($key, $val) use ($foo) { /* ... */ },
                         array_keys($arr),
                         $arr);
    },
    array(key1 => val1,
          key2 => val2,
          /* ... */));

マルチ引数ワンショット関数

「使用」ボイラープレートを防ぐために、マッピングする関数を元のスコープで定義します)。

call_user_func(
    function($f, $arr) {
        return array_map($f, array_keys($arr), $arr);
    },
    function($key, $val) use ($foo) { /* ... */ },
    array(key1 => val1,
          key2 => val2,
          /* ... */));

新機能

注意すべき興味深い点は、最後のワンショット関数には優れた汎用シグネチャがあり、array_mapによく似ていることです。これに名前を付けて再利用したい場合があります。

function array_mapk($f, $arr) {
    return array_map($f, array_keys($arr), $arr);
}

アプリケーションコードは次のようになります。

array_mapk(
    function($key, $val) use ($foo) { /* ... */ },
    array(key1 => val1,
          key2 => val2,
          /* ... */));

間接アレイウォーク

上記を書くとき、引数を参照で渡す必要があるため、array_walkは無視しました。ただし、call_user_funcを使用してこれを回避するのは簡単であることに気づきました。これはこれまでで最高のバージョンだと思います。

call_user_func(
    'array_walk',
    array(key1 => val1,
          key2 => val2,
          /* ... */),
    function($val, $key) use ($foo) { /* ... */ });

0

非常に簡単:

array_map関数のみ:インデックスキーがありません!

 $params = [4,6,2,11,20];

 $data = array_map(function($v) { return ":id{$v}";}, $params);

 array (size=5)
  0 => string ':id4' (length=4)
  1 => string ':id6' (length=4)
  2 => string ':id2' (length=4)
  3 => string ':id11' (length=5)
  4 => string ':id20' (length=5)

次に、array_keysと組み合わせます。

$data = array_map(
    function($k) use ($params) { return ":id{$k}_${params[$k]}"; },
    array_keys($params)
 );

array (size=5)
  0 => string ':id0_4' (length=6)
  1 => string ':id1_6' (length=6)
  2 => string ':id2_2' (length=6)
  3 => string ':id3_11' (length=7)
  4 => string ':id4_20' (length=7)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.