array_splice () для ассоциативных массивов

Скажем, у меня есть ассоциативный массив:

array( "color" => "red", "taste" => "sweet", "season" => "summer" ); 

и я хочу ввести в него новый элемент:

 "texture" => "bumpy" 

за вторым элементом, но сохраняя все ключи массива:

 array( "color" => "red", "taste" => "sweet", "texture" => "bumpy", "season" => "summer" ); 

есть ли функция для этого? array_splice() не будет вырезать его, он может работать только с цифровыми клавишами.

Я думаю, вам нужно сделать это вручную:

 # Insert at offset 2 $offset = 2; $newArray = array_slice($oldArray, 0, $offset, true) + array('texture' => 'bumpy') + array_slice($oldArray, $offset, NULL, true); 

Основываясь на ответе soulmerge, я создал эту удобную функцию:

 function array_insert($array,$values,$offset) { return array_slice($array, 0, $offset, true) + $values + array_slice($array, $offset, NULL, true); } 

Мне не нравится бить старую проблему до смерти, похоже, что некоторые люди уже придумали некоторые мои ответы на мои вопросы. Но я бы хотел предложить версию, которая, я думаю, немного более тщательна. Эта функция предназначена для того, чтобы чувствовать и вести себя-точно, как обычный массив array_splice (), включая его возвращаемое значение и то, как он обрабатывает недопустимые или отрицательные значения. Единственное отличие в этом отношении заключается в том, что при определении заменяющего массива (или строки или числа), а не длины, вам разрешено использовать значение null для длины вместо того, чтобы передавать счет ($ array) в качестве аргумента. Он будет считать, что многое из нуля. 0 все равно 0.

Единственная разница в функции – это, конечно, параметр $ key value, определяющий, какой ключ для получения позиции, чтобы начать вносить изменения. Зачет $ offset также остался, теперь он используется в качестве модификатора для этой начальной позиции. Ключевые конфликты всегда будут способствовать замене массива, но также вызовут предупреждение. И если ключевой параметр пуст или пуст, функция будет выглядеть только для параметра offset и вести себя как array_splice, за исключением сохранения значений ключа. Если ключ просто не найден, он будет вести себя так же, как это делает array_splice, если задано смещение, выходящее за пределы длины массива; он добавляет его до конца.

 /** * Remove or replace elements of an associative array by key value. * @param Object array $input The input associative array * @param string $key The key whose position in the array determines the start of the removed portion. * @param int $offset Adjust the start position derived from the key by this value. * If the sum is positive, it starts from the beginning of the input array. If negative, it starts from the far end. * @param int $length If length is omitted or null, remove everything from key position to the end of the array. * If positive, that many elements will be removed. * If negative, then the end of the removed portion will be that many elements from the end of the array. * @param mixed $replacement Elements from this array will be inserted at the position of the designated key. * @return array Returns the array of the extracted elements. */ function array_splice_assoc(&$input, $key, $offset = 0, $length = null, $replacement = null) { if (!is_array($input)) { $trace = debug_backtrace(); extract($trace[0]); trigger_error( __FUNCTION__."(): expects parameter 1 to be an array, ".gettype($input)." given from $file on line $line", E_USER_WARNING ); return false; } $offset = (int)$offset; $replacement = (array)$replacement; $inputLength = count($input); if (!is_null($key) && $key !== "") { $index = array_search($key, $keys = array_keys($input)); if ($index === false) { $offset = $inputLength; } $offset += $index; } $index = array_search($key, $keys = array_keys($input)); if ($index === false) { $offset = $inputLength; } $offset += $index; if ($offset < 0) { $offset += $inputLength; if ($offset < 0) { $offset = 0; } } if (is_null($length)) { $length = $inputLength; } elseif ($length < 0) { $length += $inputLength - $offset; } $extracted = array_slice($input, $offset, $length, true); $start = array_slice($input, 0, $offset, true); $end = array_slice($input, $offset + $length, $inputLength, true); $remaining = $start + $end; if (count($conflict = array_keys(array_intersect_key($remaining, $replacement)))) { $trace = debug_backtrace(); extract($trace[0]); trigger_error( __FUNCTION__."(): key conflict from $file on line $line", E_USER_WARNING ); foreach ($conflict as $key) { if (isset($start[$key])) { unset($start[$key]); } else { unset($end[$key]); } } } $input = (!empty($replacement)) ? $start + $replacement + $end : $remaining; return $extracted; } с /** * Remove or replace elements of an associative array by key value. * @param Object array $input The input associative array * @param string $key The key whose position in the array determines the start of the removed portion. * @param int $offset Adjust the start position derived from the key by this value. * If the sum is positive, it starts from the beginning of the input array. If negative, it starts from the far end. * @param int $length If length is omitted or null, remove everything from key position to the end of the array. * If positive, that many elements will be removed. * If negative, then the end of the removed portion will be that many elements from the end of the array. * @param mixed $replacement Elements from this array will be inserted at the position of the designated key. * @return array Returns the array of the extracted elements. */ function array_splice_assoc(&$input, $key, $offset = 0, $length = null, $replacement = null) { if (!is_array($input)) { $trace = debug_backtrace(); extract($trace[0]); trigger_error( __FUNCTION__."(): expects parameter 1 to be an array, ".gettype($input)." given from $file on line $line", E_USER_WARNING ); return false; } $offset = (int)$offset; $replacement = (array)$replacement; $inputLength = count($input); if (!is_null($key) && $key !== "") { $index = array_search($key, $keys = array_keys($input)); if ($index === false) { $offset = $inputLength; } $offset += $index; } $index = array_search($key, $keys = array_keys($input)); if ($index === false) { $offset = $inputLength; } $offset += $index; if ($offset < 0) { $offset += $inputLength; if ($offset < 0) { $offset = 0; } } if (is_null($length)) { $length = $inputLength; } elseif ($length < 0) { $length += $inputLength - $offset; } $extracted = array_slice($input, $offset, $length, true); $start = array_slice($input, 0, $offset, true); $end = array_slice($input, $offset + $length, $inputLength, true); $remaining = $start + $end; if (count($conflict = array_keys(array_intersect_key($remaining, $replacement)))) { $trace = debug_backtrace(); extract($trace[0]); trigger_error( __FUNCTION__."(): key conflict from $file on line $line", E_USER_WARNING ); foreach ($conflict as $key) { if (isset($start[$key])) { unset($start[$key]); } else { unset($end[$key]); } } } $input = (!empty($replacement)) ? $start + $replacement + $end : $remaining; return $extracted; } с /** * Remove or replace elements of an associative array by key value. * @param Object array $input The input associative array * @param string $key The key whose position in the array determines the start of the removed portion. * @param int $offset Adjust the start position derived from the key by this value. * If the sum is positive, it starts from the beginning of the input array. If negative, it starts from the far end. * @param int $length If length is omitted or null, remove everything from key position to the end of the array. * If positive, that many elements will be removed. * If negative, then the end of the removed portion will be that many elements from the end of the array. * @param mixed $replacement Elements from this array will be inserted at the position of the designated key. * @return array Returns the array of the extracted elements. */ function array_splice_assoc(&$input, $key, $offset = 0, $length = null, $replacement = null) { if (!is_array($input)) { $trace = debug_backtrace(); extract($trace[0]); trigger_error( __FUNCTION__."(): expects parameter 1 to be an array, ".gettype($input)." given from $file on line $line", E_USER_WARNING ); return false; } $offset = (int)$offset; $replacement = (array)$replacement; $inputLength = count($input); if (!is_null($key) && $key !== "") { $index = array_search($key, $keys = array_keys($input)); if ($index === false) { $offset = $inputLength; } $offset += $index; } $index = array_search($key, $keys = array_keys($input)); if ($index === false) { $offset = $inputLength; } $offset += $index; if ($offset < 0) { $offset += $inputLength; if ($offset < 0) { $offset = 0; } } if (is_null($length)) { $length = $inputLength; } elseif ($length < 0) { $length += $inputLength - $offset; } $extracted = array_slice($input, $offset, $length, true); $start = array_slice($input, 0, $offset, true); $end = array_slice($input, $offset + $length, $inputLength, true); $remaining = $start + $end; if (count($conflict = array_keys(array_intersect_key($remaining, $replacement)))) { $trace = debug_backtrace(); extract($trace[0]); trigger_error( __FUNCTION__."(): key conflict from $file on line $line", E_USER_WARNING ); foreach ($conflict as $key) { if (isset($start[$key])) { unset($start[$key]); } else { unset($end[$key]); } } } $input = (!empty($replacement)) ? $start + $replacement + $end : $remaining; return $extracted; } 

Итак, тогда …

 $array1 = array( "fruit1" => "apple", "vegetable1" => "carrot", "vegetable2" => "potato", "fruit2" => "orange", "fruit3" => "banana", "fruit4" => "pear" ); $array2 = array( "snack" => "chips", "vegetable3" => "green bean", "vegetable1" => "corn" ); $vegetables = array_splice_assoc($array1, "fruit1", 1, -3); print_r($array1); print_r($vegetables); array_splice_assoc($array2, "vegetable3", -1, 1, $vegetables); print_r($array2); /* Output is: Array ( [fruit1] => apple [fruit2] => orange [fruit3] => banana [fruit4] => pear ) Array ( [vegetable1] => carrot [vegetable2] => potato ) PHP Warning: array_splice_assoc(): key conflict from /var/www/php/array_splice_assoc.php on line 97 in /var/www/php/array_splice_assoc.php on line 65 Array ( [vegetable1] => carrot [vegetable2] => potato [vegetable3] => green bean ) */ 

Это также может быть более простым способом замены отдельных ключей массива при сохранении его положения без необходимости проходить через array_values ​​и array_combine.

 $array3 = array( "vegetable1" => "carrot", "vegetable2" => "potato", "vegetable3" => "tomato", "vegetable4" => "green bean", "vegetable5" => "corn" ); array_splice_assoc($array3, null, 2, 1, array("fruit1" => $array3['vegetable3'])); print_r($array3); /* OUTPUT: Array ( [vegetable1] => carrot [vegetable2] => potato [fruit1] => tomato [vegetable4] => green bean [vegetable5] => corn ) */ 

EDIT: Я только что обнаружил, что, по-видимому, array_merge () не может отличить ассоциативные ключи массива, которые просто являются номерами, и регулярными последовательными ключами. Объединение массивов с помощью оператора + вместо array_merge () позволяет избежать этой проблемы.

Я не уверен, есть ли для этого функция, но вы можете проходить через свой массив, хранить индекс и использовать array_push.

Ну, вы можете перестроить массив с нуля. Но самый простой способ пройти через ассоциативный массив в определенном порядке – это сохранить отдельный массив упорядочения. Вот так:

 $order=array('color','taste','texture','season'); foreach($order as $key) { echo $unordered[$key]; } 

Вот еще один способ:

 function array_splice_assoc(&$input, $offset, $length = 0, $replacement = array()) { $keys = array_keys($input); $values = array_values($input); array_splice($keys, $offset, $length, array_keys($replacement)); array_splice($values, $offset, $length, array_values($replacement)); $input = array_combine($keys, $values); } 

Основываясь на решении, предоставленном ragulka и soulmerge, я создал slightly different function которая позволяет вам указать «ключ» вместо смещения.

 <?php /** * Insert values in a associative array at a given position * * @param array $array * The array in which you want to insert * @param array $values * The key => values you want to insert * @param string $pivot * The key position to use as insert position. * @param string $position * Where to insert the values relative to given $position. * Allowed values: 'after' - default or 'before' * * @return array * The resulted array with $values inserted a given position */ function array_insert_at_position($array, $values, $pivot, $position = 'after'){ $offset = 0; foreach($array as $key => $value){ ++$offset; if ($key == $pivot){ break; } } if ($position == 'before'){ --$offset; } return array_slice($array, 0, $offset, TRUE) + $values + array_slice($array, $offset, NULL, TRUE) ; } ?> 

Существует очень простой способ сделать это, что я придумал tonight.It будет искать ключ, сплайсировать его, как обычно, и вернуть удаленный элемент, как нормальная функция.

 function assoc_splice($source_array, $key_name, $length, $replacement){ return array_splice($source_array, array_search($key_name, array_keys($source_array)), $length, $replacement); } 

Это работает как array_splice , но сохраняет ключи вставленного массива:

  function array_splicek(&$array, $offset, $length, $replacement) { if (!is_array($replacement)) { $replacement = array($replacement); } $out = array_slice($array, $offset, $length); $array = array_slice($array, 0, $offset, true) + $replacement + array_slice($array, $offset + $length, NULL, true); return $out; } 

Вы используете это, как вы бы array_splice , но просто добавьте k в конец. (ответ ragulka хорош, но это облегчает адаптацию существующего кода.) Так, например,

 $a = array("color" => "red", "taste" => "sweet", "season" => "summer"); $b = array("texture" => "bumpy"); 

Вместо

 array_splice($a, 2, 0, $b); 

использование

 array_splicek($a, 2, 0, $b); 

Тогда $a будет содержать результат, который вы ищете.

Мое решение имитирует array_splice точно, вторым параметром теперь является String $key, вместо Int $offset,

 function array_splice_assoc ( &$input ,$key, $length = 0 , $replacement = null ){ $keys = array_keys( $input ); $offset = array_search( $key, $keys ); if($replacement){ $values = array_values($input); $extracted_elements = array_combine(array_splice($keys, $offset, $length, array_keys($replacement)),array_splice($values, $offset, $length, array_values($replacement))); $input = array_combine($keys, $values); } else { $extracted_elements = array_slice($input, $offset, $length); } return $extracted_elements; } 

Таким образом, чтобы получить результат, который вы требуете,

 $array = array( "color" => "red", "taste" => "sweet", "season" => "summer" ); $replacement = array("texture" => "bumpy"); array_splice_assoc ($array ,"season", 0, $replacement); 

Вывод

 Array ( [color] => red [taste] => sweet [texture] => bumpy [season] => summer ) 

Важное примечание. Это не будет работать, если ключи не находятся в массиве.

Мое решение (я люблю использовать собственные функции php-массива);

 $startIndex = array_search($firstKey, array_keys($arr); $endIndex = array_search($secondKey, array_keys($arr)); array_splice($arr, $startIndex, $endIndex - $startIndex); 

Это довольно просто, и вы можете легко превратить его в функцию.

 function insrt_to_offest($targetArr, $toBeEmbed, $indAfter) { $ind = array_search($indAfter, array_keys($targetArr)); $offset = $ind + 1; # Insert at offset 2 $newArray = array_slice($targetArr, 0, $offset, true) + $toBeEmbed + array_slice($targetArr, $offset, NULL, true); return $newArray; } $features = array( "color" => "red", "taste" => "sweet", "season" => "summer" ); print_r($features); $toBeEmbed = array("texture" => "bumpy"); $newArray = insrt_to_offest($features, $toBeEmbed, 'taste'); print_r($newArray); 

Подобно ответу @ Luxian, я пришел к аналогичному методу и настроил его как array_splice_key. https://gist.github.com/4499117

 /** * Insert another array into an associative array after the supplied key * * @param string $key * The key of the array you want to pivot around * @param array $source_array * The 'original' source array * @param array $insert_array * The 'new' associative array to merge in by the key * * @return array $modified_array * The resulting merged arrays */ function array_splice_after_key( $key, $source_array, $insert_array ) { return array_splice_key( $key, $source_array, $insert_array ); } /** * Insert another array into an associative array before the supplied key * * @param string $key * The key of the array you want to pivot around * @param array $source_array * The 'original' source array * @param array $insert_array * The 'new' associative array to merge in by the key * * @return array $modified_array * The resulting merged arrays */ function array_splice_before_key( $key, $source_array, $insert_array ) { return array_splice_key( $key, $source_array, $insert_array, -1 ); } /** * Insert another array into an associative array around a given key * * @param string $key * The key of the array you want to pivot around * @param array $source_array * The 'original' source array * @param array $insert_array * The 'new' associative array to merge in by the key * @param int $direction * Where to insert the new array relative to given $position by $key * Allowed values: positive or negative numbers - default is 1 (insert after $key) * * @return array $modified_array * The resulting merged arrays */ function array_splice_key( $key, $source_array, $insert_array, $direction = 1 ){ $position = array_search( $key, array_keys( $source_array ) ) + $direction; // setup the return with the source array $modified_array = $source_array; if( count($source_array) < $position && $position != 0 ) { // push one or more elements onto the end of array array_push( $modified_array, $insert_array ); } else if ( $position < 0 ){ // prepend one or more elements to the beginning of an array array_unshift( $modified_array, $insert_array ); } else { $modified_array = array_slice($source_array, 0, $position, true) + $insert_array + array_slice($source_array, $position, NULL, true); } return $modified_array; }