Изменение ключей массива в функции array_walk?

Я использую функции массива, чтобы преобразовать строку, связанную с строкой, в ассоциативный массив.

$piper = "|k=f|p=t|e=r|t=m|";

$piper = explode("|",$piper);

$piper = array_filter($piper);

function splitter(&$value,$key) {

    $splitted = explode("=",$value);
    $key = $splitted[0];
    $value = $splitted[1];

}

array_walk($piper, 'splitter');

var_dump($piper);

это дает мне

array (size=4)
  1 => string 'f' (length=1)
  2 => string 't' (length=1)
  3 => string 'r' (length=1)
  4 => string 'm' (length=1)

где я хочу:

array (size=4)
  "k" => string 'f' (length=1)
  "p" => string 't' (length=1)
  "e" => string 'r' (length=1)
  "t" => string 'm' (length=1)

но ключи не изменяются. Есть ли какая-либо функция массива, с которой я могу перебирать массив и менять ключи и значения?

Ответы

Ответ 1

В документации array_walk (описание функции обратного вызова):

Можно изменять только значения массива; его структура не могут быть изменены, то есть программист не может добавлять, отменять или изменять порядок элементы. Если обратный вызов не соблюдает это требование, поведение этой функции undefined и непредсказуемо.

Это означает, что вы не можете использовать array_walk для изменения ключей итерированного массива. Однако вы можете создать с ним новый массив:

$result = array();
array_walk($piper, function (&$value,$key) use (&$result) {
    $splitted = explode("=",$value);
    $result[ $splitted[0] ] = $splitted[1];
});
var_dump($result);

Тем не менее, я думаю, что если бы это был я, я использовал бы здесь регулярное выражение (вместо "взрывающегося взорванного" ):

$piper = "|k=f|p=t|e=r|t=m|";
preg_match_all('#([^=|]*)=([^|]*)#', $piper, $matches, PREG_PATTERN_ORDER);
$piper = array_combine($matches[1], $matches[2]);
var_dump($piper);

Ответ 2

Для этого лучше использовать foreach. В следующем примере показана обработка записи, добавление ее правой клавишей и удаление исходной записи.

$piper = "|k=f|p=t|e=r|t=m|";
$piper = array_filter(explode("|", $piper));

foreach ($piper as $index => $value) {
    list($key, $value) = explode("=", $value);
    $piper[$key] = $value;
    unset($piper[$index]);
}

Позаботьтесь, чтобы у вас не было ключей, похожих на индекс.

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

foreach ($piper as &$value) {
    list($keys[], $value) = explode("=", $value);
}
unset($value);

$piper = array_combine($keys, $piper);

Это не приводит к возникновению каких-либо проблем, но только с дублирующими ключами. Но вы можете проверить эту проблему после foreach, никакие данные не будут потеряны.

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

$result = array();
foreach ($piper as $value) {
    list($key, $value) = explode("=", $value);
    $result[$key] = $value;
}

Ответ 3

Почему бы не построить новый массив, который имеет нужные ключи и значения из $piper?

$piper2 = array();
foreach ($piper as $k => $val)
{
  $splitted = explode("=", $val);
  $key = $splitted[0];
  $value = $splitted[1];

  $piper2[$key] = $value;
}

$piper = $piper2; // if needed

Ответ 4

Использование array_reduce сделает трюк

$piper = "|k=f|p=t|e=r|t=m|";

$piper = explode("|",$piper);

$piper = array_filter($piper);

function splitter($result, $item) {
    $splitted = explode("=",$item);
    $key = $splitted[0];
    $value = $splitted[1];

    $result[$key] = $value;

    return $result;
}

$piper = array_reduce($piper, 'splitter', array());

var_dump($piper);

на основе этого: http://www.danielauener.com/howto-use-array_map-on-associative-arrays-to-change-values-and-keys/

Ответ 5

Это моя рекурсивная функция, которая может изменять не только значения массива как array_walk_recursive() , но также ключи данного массива. Он также сохраняет порядок массива:fooobar.com/info/897708/...