提问人:Pekka 提问时间:11/23/2009 最后编辑:aksuPekka 更新时间:8/30/2021 访问量:49678
array_splice() 用于关联数组
array_splice() for associative arrays
问:
假设我有一个关联数组:
array(
"color" => "red",
"taste" => "sweet",
"season" => "summer"
);
我想在其中引入一个新元素:
"texture" => "bumpy"
在第 2 项后面,但保留所有数组键:
array(
"color" => "red",
"taste" => "sweet",
"texture" => "bumpy",
"season" => "summer"
);
有没有功能可以做到这一点?array_splice()
不会削减它,它只能使用数字键。
答:
我不确定是否有函数,但您可以遍历数组,存储索引并使用array_push。
好吧,您可以从头开始重建阵列。但是,按特定顺序遍历关联数组的最简单方法是保留一个单独的排序数组。这样:
$order=array('color','taste','texture','season');
foreach($order as $key) {
echo $unordered[$key];
}
评论
我认为您需要手动执行此操作:
# Insert at offset 2
$offset = 2;
$newArray = array_slice($oldArray, 0, $offset, true) +
array('texture' => 'bumpy') +
array_slice($oldArray, $offset, NULL, true);
评论
$offset + 1
在底部array_slice替换而不是在该位置前置
根据 soulmerge 的回答,我创建了这个方便的函数:
function array_insert($array,$values,$offset) {
return array_slice($array, 0, $offset, true) + $values + array_slice($array, $offset, NULL, true);
}
评论
根据 ragulka 和 soulmerge 提供的解决方案,我创建了一个稍微不同的函数
,让您指定“键”而不是偏移量。
<?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)
;
}
?>
与@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;
}
我今晚想出了一个超级简单的方法来做到这一点。它将搜索一个键,像往常一样拼接它,然后像正常函数一样返回已删除的元素。
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;
}
您可以像以前一样使用它,但只需在末尾添加一个。(Ragulka 的回答很好,但这样可以更容易地调整现有代码。所以,例如array_splice
k
$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
这是另一种方法:
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);
}
我讨厌把一个老问题打死,似乎有些人已经想出了一些与我类似的答案。但我想提供一个我认为更彻底的版本。此函数旨在与常规 array_splice() 函数完全相同,包括其返回值以及它如何处理无效或负值。这方面的唯一区别是,在定义替换数组(或字符串或数字)而不是长度时,可以使用 null 值作为长度,而不必将 count($array) 作为参数传递。它将从 null 中假设很多。不过,0 仍然是 0。
功能上唯一的区别当然是 $key 值参数,它指定从哪个键派生位置以开始进行更改。$offset也被保留了下来,现在用作该初始位置的修饰符。键冲突将始终有利于替换阵列,但也会触发警告。如果键参数为 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;
}
那么......
$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
)
*/
编辑: 我刚刚发现,显然 array_merge() 无法真正区分恰好是数字的关联数组键和常规顺序键之间的区别。使用 + 运算符而不是 array_merge() 合并数组可以避免此问题。
我的解决方案完全模仿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);
它非常简单,您可以轻松地将其转换为功能。
评论
0
false
array_search()
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);
我需要在键指定的项目之后插入新项目,而不是数字索引(偏移量),所以我最后使用(受 dnagirl 的回答启发)重新创建数组:foreach
$new_fields = array();
foreach($original_fields as $key => $value) {
$new_fields[$key] = $value;
if ($key == 'the_key_before_insertion') {
// add the inserted_key => inserted_value now
$new_fields['inserted_key'] = 'inserted_value';
}
}
评论