Я использую функции массива, чтобы преобразовать строку с разделителями строк в ассоциативный массив.
$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)
но ключи не изменяются. Есть ли какая-либо функция массива, с которой я могу перебирать массив и менять ключи и значения?
Это сказано в документации array_walk (описывающей функцию обратного вызова):
Можно изменять только значения массива; его структура не может быть изменена, т. е. программист не может добавлять, отменять или изменять порядок элементов. Если обратный вызов не соблюдает это требование, поведение этой функции не определено и непредсказуемо.
Это означает, что вы не можете использовать 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);
Почему бы не построить новый массив, который имеет нужные ключи и значения из $ piper?
$piper2 = array(); foreach ($piper as $k => $val) { $splitted = explode("=", $val); $key = $splitted[0]; $value = $splitted[1]; $piper2[$key] = $value; } $piper = $piper2; // if needed
Вы можете лучше использовать 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]); }
с$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 ($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; }
Использование 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/