array_splice()用于关联数组

Pek*_*ica 44 php arrays

假设我有一个关联数组:

array(
  "color" => "red",
  "taste" => "sweet",
  "season" => "summer"
);
Run Code Online (Sandbox Code Playgroud)

我想在其中引入一个新元素:

"texture" => "bumpy" 
Run Code Online (Sandbox Code Playgroud)

在第二项后面,但保留所有数组键:

array(
  "color" => "red",
  "taste" => "sweet",
  "texture" => "bumpy", 
  "season" => "summer"
);
Run Code Online (Sandbox Code Playgroud)

有功能吗?array_splice()不会削减它,它只能使用数字键.

sou*_*rge 105

我认为您需要手动执行此操作:

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

  • 我们必须在PHP中执行此操作非常难看,但这是正确的解决方案. (4认同)
  • @JoelCox - PHP阵列的订购不仅仅是意外事故或偶然事件.它们是以这种方式明确实现的.PHP关联数组是有序映射(http://php.net/manual/en/language.types.array.php).我想,永远不要说永远不会说,但这种语言的未来版本不太可能改变. (3认同)
  • 我最终这样做了.谢谢. (2认同)

rag*_*lka 23

根据soulmerge的回答,我创建了这个方便的功能:

function array_insert($array,$values,$offset) {
    return array_slice($array, 0, $offset, true) + $values + array_slice($array, $offset, NULL, true);  
}
Run Code Online (Sandbox Code Playgroud)


Cla*_*ore 7

我讨厌将旧问题打败,似乎有些人已经想出了一些与我相似的答案.但我想提供一个我认为更彻底的版本.此函数旨在感觉和行为 - 就像常规的array_splice()一样,包括它的返回值以及它如何处理无效或负值.这方面的唯一区别是,在定义替换数组(或字符串或数字)而不是长度时,允许使用空值作为长度,而不必将count($ array)作为参数传递.它将假设很多来自null.0仍然是0.

函数的唯一区别当然是$ key value参数,指定从哪个键导出开始进行更改的位置.$ offset也被留下,现在用作初始位置的修饰符.键冲突总是有利于替换阵列,但也会触发警告.如果key参数为null或空白,则除了保持键值之外,该函数将仅查看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;
}
Run Code Online (Sandbox Code Playgroud)

那么......

$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
)
*/
Run Code Online (Sandbox Code Playgroud)

这也可以是一种更简单的方法来替换单个数组键,同时保持其位置,而无需通过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
)
*/
Run Code Online (Sandbox Code Playgroud)

编辑:我刚刚发现,显然array_merge()无法真正区分恰好是数字的关联数组键和常规顺序键之间的区别.使用+运算符而不是array_merge()合并数组可以避免此问题.