2015-02-13 4 views
1

мне нужно перебирать массив, который выглядит следующим образом:array_map с доступом к ключам

$myArray = array(
    'key1' => array('subkey' => 'subvalue'), 
    'key2' => array('subkey' => 'subvalue'), 
) 

В каждой вложенной ассоциативного массива, я хочу добавить пару ключ-значение на основе внешнего ключа, как это :

$myNewArray = array(
    'key1' => array('subkey' => 'subvalue', 'newkey' => 'only for key1'), 
    'key2' => array('subkey' => 'subvalue'), 
) 

в идеале, я ищу что-то вроде:

$myNewArray = array_map(function($key, $value) { 
    if ($key == 'key1') { 
     $value['newkey'] = 'only for key1'; 
    } 
    return $value; 
}, $myArray); 

Однако, это, очевидно, не работает, как callback не заданы два параметра, а только один. Я мог бы сделать что-то вроде этого:

$myNewArray = array_map(function($key, $value) { 
    if ($key == 'key1') { 
     $value['newkey'] = 'only for key1'; 
    } 
    return WHAT?? 
}, array_keys($myArray), $myArray); 

Однако, что мне вернуть? Кажется, что всегда создается новый массив, то есть отбрасывает мои строковые ключи (key1 и key2), в то время как один массив array_map() сохраняет их.

Я могу использовать array_walk(), но у него есть довольно странный API (перевернутый порядок параметров, массив, переданный по ссылке и т. Д.), Поэтому я бы предпочел, если это можно было бы достичь, используя array_map(). Может это?

ответ

1

Боюсь array_walk() это способ сделать это ,

Если вы не любите array_walk() и настаиваете на том, чтобы сделать это с array_map(), ну, это возможно. Она включает в себя использование также array_keys(), array_values() и array_combine(), это долго и некрасиво, но выполнимо:

$myNewArray = array_combine(
    array_keys($myArray), 
    array_map(
     function($key, $value) { 
      if ($key == 'key1') { 
       $value['newkey'] = 'only for key1'; 
      } 
      return $value; 
     }, 
     array_keys($myArray), 
     array_values($myArray)  // can omit array_values() and use $myArray 
    ) 
); 

Вы также можете сделать это с помощью array_reduce(), но это тот же беспорядок:

$myNewArray = array_reduce(
    array_keys($myArray), 
    function (array $carry, $key) use ($myArray) { 
     $value = $myArray[$key]; 
     if ($key == 'key1') { 
      $value['newkey'] = 'only for key1'; 
     } 
     $carry[$key] = $value; 
     return $carry; 
    }, 
    array() 
); 

Я надеюсь, что у вас есть условие более сложное, чем $key == 'key1', потому что только для этого не стоит писать сложный обход. Не проще ли просто получить доступ к правильному элементу и изменить его?

$myArray['key1']['newkey'] = 'only for key1'; 
+0

Да, преобразование намного сложнее, я просто дал минимальный пример, который показывает вызов.Спасибо за ваш ответ, первый метод на самом деле не выглядит слишком уродливым для меня, хотя метод array_walk(), безусловно, будет короче. Мне просто не нравится передавать массивы по ссылке. – Borek

1

array_map передает только не ключ. array_walk очень похож на array_map. Просто определите значение как ссылку. Он берет ключ, где array_map нет. Кроме того, это изменяет $myArray:

array_walk($myArray, function(&$value, $key) { 
    if ($key == 'key1') { 
     $value['newkey'] = 'only for key1'; 
    } 
}); 

Из PHP инструкции, там, похоже, быть array_map метод с использованием array_keys в другой массив:

$myNewArray = array_combine(array_keys($myArray), array_map(function($key, $value) { 
    if ($key == 'key1') { 
     $value['newkey'] = 'only for key1'; 
    } 
    return $value; 
}, array_keys($myArray), $myArray)); 
+0

Да, это работает, однако, как ваш пример показывает, то API сбивает с толку, и это легко сделать ошибку - $ myNewArray в вашем примере будет верно :) Но я понимаю, спасибо. – Borek

+0

Я просто заметил, что когда я работал с 'array_map'. Ред. – AbraCadaver

+0

Ваш второй пример вернет массив ассоциативных массивов, который отличается от просто ассоциативного массива. – Borek