array_splice
(PHP 4, PHP 5, PHP 7, PHP 8)
array_splice — 配列の一部を削除し、他の要素で置換する
説明
配列 array
から offset
および length
で指定された要素を削除し、配列 replacement
でそれを置換します。
注意:
array
の配列の数値添字は保存されないことに注意しましょう。
注意:
replacement
が配列でない場合は、 型変換 を行います (つまり(array) $replacement
とします)。 たとえばreplacement
にオブジェクトやnull
などを指定した場合に、 予期せぬ動きをする可能性があります。
パラメータ
array
-
入力の配列。
offset
-
offset
が正の場合、削除される部分は 配列array
の最初から指定オフセットの ぶんだけ進んだ位置からとなります。offset
が負の場合、削除される部分は、array
の末尾から数えた位置からとなります。 length
-
length
が省略された場合、offset
から配列の最後までが全て削除されます。length
が指定され、正の場合、複数の要素が削除されます。負の
length
が指定された場合、削除される部分の末尾の位置は配列の末尾を基準にして計算されます。length
にゼロを指定した場合は、どの要素も削除しません。ヒントreplacement
も指定した場合にoffset
から配列の最後まで全てを削除するには、length
を求めるためにcount($input)
を使用してください。 replacement
-
配列
replacement
が指定された場合、 削除された要素は、この配列の要素で置換されます。offset
およびlength
で何も削除しないと指定した場合、配列replacement
の要素はoffset
で指定された位置に挿入されます。注意:
置換される配列のキーは保存されないことに注意してください。
もし
replacement
に一つしか要素がない場合、 要素そのものが配列やオブジェクトあるいはnull
でない限り、array()
や 角括弧 で括る必要はありません。
戻り値
抽出された要素を含む配列を返します。
変更履歴
バージョン | 説明 |
---|---|
8.0.0 |
length は、nullable になりました。
|
例
例1 array_splice() の例
<?php
$input = array("red", "green", "blue", "yellow");
array_splice($input, 2);
var_dump($input);
$input = array("red", "green", "blue", "yellow");
array_splice($input, 1, -1);
var_dump($input);
$input = array("red", "green", "blue", "yellow");
array_splice($input, 1, count($input), "orange");
var_dump($input);
$input = array("red", "green", "blue", "yellow");
array_splice($input, -1, 1, array("black", "maroon"));
var_dump($input);
?>
上の例の出力は以下となります。
array(2) { [0]=> string(3) "red" [1]=> string(5) "green" } array(2) { [0]=> string(3) "red" [1]=> string(6) "yellow" } array(2) { [0]=> string(3) "red" [1]=> string(6) "orange" } array(5) { [0]=> string(3) "red" [1]=> string(5) "green" [2]=> string(4) "blue" [3]=> string(5) "black" [4]=> string(6) "maroon" }
例2 同じ動きをする、array_splice() の様々な例
以下の文は、すべて2つとも同じ意味です:
<?php
// $input に 2 つの要素を追加します
array_push($input, $x, $y);
array_splice($input, count($input), 0, array($x, $y));
// $input の最後の要素を削除します
array_pop($input);
array_splice($input, -1);
// $input の最初の要素を削除します
array_shift($input);
array_splice($input, 0, 1);
// $input の先頭に要素を挿入します
array_unshift($input, $x, $y);
array_splice($input, 0, 0, array($x, $y));
// インデックス $x の $input を置き換えます
$input[$x] = $y; // キーがオフセットと等価な配列に対して
array_splice($input, $x, 1, $y);
?>
User Contributed Notes 38 notes
array_splice, split an array into 2 arrays. The returned arrays is the 2nd argument actually and the used array e.g $input here contains the 1st argument of array, e.g
<?php
$input = array("red", "green", "blue", "yellow");
print_r(array_splice($input, 3)); // Array ( [0] => yellow )
print_r($input); //Array ( [0] => red [1] => green [2] => blue )
?>
if you want to replace any array value do simple like that,
first search the array index you want to replace
<?php $index = array_search('green', $input);// index = 1 ?>
and then use it as according to the definition
<?php
array_splice($input, $index, 1, array('mygreeen')); //Array ( [0] => red [1] => mygreeen [2] => blue [3] => yellow )
?>
so here green is replaced by mygreen.
here 1 in array_splice above represent the number of items to be replaced. so here start at index '1' and replaced only one item which is 'green'
When trying to splice an associative array into another, array_splice is missing two key ingredients:
- a string key for identifying the offset
- the ability to preserve keys in the replacement array
This is primarily useful when you want to replace an item in an array with another item, but want to maintain the ordering of the array without rebuilding the array one entry at a time.
<?php
function array_splice_assoc(&$input, $offset, $length, $replacement) {
$replacement = (array) $replacement;
$key_indices = array_flip(array_keys($input));
if (isset($input[$offset]) && is_string($offset)) {
$offset = $key_indices[$offset];
}
if (isset($input[$length]) && is_string($length)) {
$length = $key_indices[$length] - $offset;
}
$input = array_slice($input, 0, $offset, TRUE)
+ $replacement
+ array_slice($input, $offset + $length, NULL, TRUE);
}
$fruit = array(
'orange' => 'orange',
'lemon' => 'yellow',
'lime' => 'green',
'grape' => 'purple',
'cherry' => 'red',
);
// Replace lemon and lime with apple
array_splice_assoc($fruit, 'lemon', 'grape', array('apple' => 'red'));
// Replace cherry with strawberry
array_splice_assoc($fruit, 'cherry', 1, array('strawberry' => 'red'));
?>
Note: I have not tested this with negative offsets and lengths.
array_splice() does not preserve numeric keys. The function posted by "weikard at gmx dot de" won't do that either because array_merge() does not preserve numeric keys either.
Use following function instead:
<?php
function arrayInsert($array, $position, $insertArray)
{
$ret = [];
if ($position == count($array)) {
$ret = $array + $insertArray;
}
else {
$i = 0;
foreach ($array as $key => $value) {
if ($position == $i++) {
$ret += $insertArray;
}
$ret[$key] = $value;
}
}
return $ret;
}
?>
Example:
<?php
$a = [
295 => "Hello",
58 => "world",
];
$a = arrayInsert($a, 1, [123 => "little"]);
/*
Output:
Array
(
[295] => Hello
[123] => little
[58] => world
)
*/
?>
It preserves numeric keys. Note that the function does not use a reference to the original array but returns a new array (I see absolutely no reason how the performance would be increased by using a reference when modifying an array through PHP script code).
just useful functions to move an element using array_splice.
<?php
// info at danielecentamore dot com
// $input (Array) - the array containing the element
// $index (int) - the index of the element you need to move
function moveUp($input,$index) {
$new_array = $input;
if((count($new_array)>$index) && ($index>0)){
array_splice($new_array, $index-1, 0, $input[$index]);
array_splice($new_array, $index+1, 1);
}
return $new_array;
}
function moveDown($input,$index) {
$new_array = $input;
if(count($new_array)>$index) {
array_splice($new_array, $index+2, 0, $input[$index]);
array_splice($new_array, $index, 1);
}
return $new_array;
}
$input = array("red", "green", "blue", "yellow");
$newinput = moveUp($input, 2);
// $newinput is array("red", "blue", "green", "yellow")
$input = moveDown($newinput, 1);
// $input is array("red", "green", "blue", "yellow")
?>
If you want to append null values wrap them in an array:
<?php
$a = array('Hey', 'hey', 'my', 'my');
array_splice($a, 1, 0, null);
print_r($a);
?>
Array
(
[0] => Hey
[1] => hey
[2] => my
[3] => my
)
<?php
$b = array('Hey', 'hey', 'my', 'my');
array_splice($b, 1, 0, array(null));
print_r($b);
?>
Array
(
[0] => Hey
[1] =>
[2] => hey
[3] => my
[4] => my
)
array_splice dynamically updates the total number of entries into the array. So for instance I had a case where I needed to insert a value into every 4th entry of the array from the back. The problem was when it added the first, because the total number was dynamically updated, it would only add after the 3rd then the 2nd and so one. The solution I found is to track the number of inserts which were done and account for them dynamically.
Code:
<?php
$modarray = array_reverse($mili);
$trig=1;
foreach($modarray as $rubber => $glue) {
if($rubber!="<BR>") {
$i++;
$b++;
if ($i==4) {
$trig++;
if($trig<=2) {
array_splice($modarray,$b,0,"<BR>");
}elseif($trig>=3){
array_splice($modarray,$b+($trig-2),0,"<BR>");
}
$i=0;
};
};
};
$fixarray = array_reverse($modarray);
?>
You cannot insert with array_splice an array with your own key. array_splice will always insert it with the key "0".
<?php
// [DATA]
$test_array = array (
row1 => array (col1 => 'foobar!', col2 => 'foobar!'),
row2 => array (col1 => 'foobar!', col2 => 'foobar!'),
row3 => array (col1 => 'foobar!', col2 => 'foobar!')
);
// [ACTION]
array_splice ($test_array, 2, 0, array ('rowX' => array ('colX' => 'foobar2')));
echo '<pre>'; print_r ($test_array); echo '</pre>';
?>
[RESULT]
Array (
[row1] => Array (
[col1] => foobar!
[col2] => foobar!
)
[row2] => Array (
[col1] => foobar!
[col2] => foobar!
)
[0] => Array (
[colX] => foobar2
)
[row3] => Array (
[col1] => foobar!
[col2] => foobar!
)
)
But you can use the following function:
function array_insert (&$array, $position, $insert_array) {
$first_array = array_splice ($array, 0, $position);
$array = array_merge ($first_array, $insert_array, $array);
}
<?php
// [ACTION]
array_insert ($test_array, 2, array ('rowX' => array ('colX' => 'foobar2')));
echo '<pre>'; print_r ($test_array); echo '</pre>';
?>
[RESULT]
Array (
[row1] => Array (
[col1] => foobar!
[col2] => foobar!
)
[row2] => Array (
[col1] => foobar!
[col2] => foobar!
)
[rowX] => Array (
[colX] => foobar2
)
[row3] => Array (
[col1] => foobar!
[col2] => foobar!
)
)
[NOTE]
The position "0" will insert the array in the first position (like array_shift). If you try a position higher than the langth of the array, you add it to the array like the function array_push.
key-safe:
<?php
function array_kslice ($array, $offset, $length = 0) {
$k = array_slice (array_keys ($array), $offset, $length);
$v = array_slice (array_values ($array), $offset, $length);
for ($i = 0; $i < count ($k); $i ++) $r[$k[$i]] = $v[$i];
return $r;
}
?>
smth like this. hope you like it more than versions above :)
array_splice with preserve keys
<?php
function array_splice_preserve_keys(&$array, $from, $length = null) {
$result = array_slice($array, $from, $length, true);
$array = array_slice($array, $from + $length, null, true);
return $result;
}
?>
Example:
<?php
$array = [
1 => 'a',
2 => 'b',
26 => 'z'
];
var_dump(array_splice_preserve_keys($array, 0, 1), $array);
/**
* array(1) {
* [1]=>
* string(1) "a"
* }
* array(2) {
* [2]=>
* string(1) "b"
* [26]=>
* string(1) "z"
* }
*/
?>
Using array_splice when you traverse array with internal pointer's function reset the array, eg:
<?php
end($arrOfData);
$last = key($arrOfData);
reset($arrOfData);
while (($data = current($arrOfData))) {
if ($last === key($arrOfData)) {
array_splice($arrOfData, $last, 1);
// current($arrOfData) => first value of $arrOfData
}
}
Appending arrays
If you have an array $a2 whose values you would like to append to an array $a1 then four methods you could use are listed below in order of increasing time. The last two methods took significantly more time than the first two. The most surprising lesson is that using the & incurs a time hit.
<?php
foreach ($a2 as $elem) $a1[]=$elem;
foreach ($a2 as &$elem) $a1[]=$elem;
array_splice ($a1, count($a1), 0, $a2);
$a1 = array_merge($a1, $a2);
?>
Csaba Gabor from Vienna
Maybe it will help someone else: I was trying to strip off the last part of an array using this section, more or less as follows:
<?php array_splice($array, $offset); ?>
Now it could occur in my code that <?php $offset === 0 ?>, in which case the array is returned as-is and not, as you might expect, an empty array because everything is stripped off. Obviously it is not really useful anyway to "strip off everything", but I was reminded of that the hard way and this may spare someone some time, hopefully.
[ Editor's Note: If you're not concerned with the indexes being contiguously numbered (such as for an associative array) then unset($ar[$ind]); will accomplish the same as the code below without requiring splice/splice/merge. If contiguous numbering IS a concern (such as for indexed arrays), you can still save time by using: unset($ar[$ind]); $ar = array_values($ar); ]
Removing elements from arrays
This works better - much quicker
<?php
$ar = array("einstein", "bert", "colin", "descartes", "renoir");
$a = array_slice($ar, 0, $ind);
$b = array_slice($ar, $ind + 1);
$ar = array_merge($a, $b);
?>
Splicing with NULL as replacement may result in unexpected behavior too. Typecasting NULL into an array results in an empty array (as "(array)NULL" equals "array()"). That means, instead of creating an element with value NULL just no new element ist created (just as if there was no replacement specified).
If you want the splicing to create a new element with value NULL you have to use "array(NULL)" instead of NULL.
You should expect this if you read the explanation carefully, but just as objects are considered as a special case for replacement, NULL should be too.
The explanation of replacement better should read: "If replacement is just one element it is not necessary to put array() around it, unless the element is an array itself, an object or NULL."
And the note better should be: "If replacement is not an array, it will be typecast to one (i.e. (array) $parameter). This may result in unexpected behavior when using an object or NULL replacement."
jmtc
A reference is made to INSERT'ing into an array here with array_splice, however its not explained very well. I hope this example will help others find what took me days to research.
<?php
$original_array = array(1,2,3,4,5);
$insert_into_key_position = 3;
$item_to_insert = "blue";
$returned = array_splice($original_array, $insert_into_key_position, 0, $item_to_insert);
// $original_array will now show:
// 1,2,3,blue,4,5
?>
Remember that you are telling the array to insert the element into the KEY position. Thus the elements start with key 0 and so on 0=>1, 1=>2, 2=>3, 3=>blue, 4=>4, 5=>5. And walla, you've inserted. I can't say if this is of any value for named keys, or multidimensional arrays. However it does work for single dimensional arrays.
$returned should be an empty array as nothing was returned. This would have substance if you were doing a replace instead.
Here's my own take on an array slice method that preserves keys from an associative array.
<?php
/**
* Array slice function that preserves associative keys
*
* @function associativeArraySlice
*
* @param Array $array Array to slice
* @param Integer $start
* @param Integer $end
*
* @return Array
*/
function associativeArraySlice($array, $start, $end) {
// Method param restrictions
if($start < 0) $start = 0;
if($end > count($array)) $end = count($array);
// Process vars
$new = Array();
$i = 0;
// Loop
foreach($array as $key => $value) {
if($i >= $start && $i < $end) {
$new[$key] = $value;
}
$i++;
}
return($new);
}
?>
To split an associative array based on it's keys, use this function:
<?php
function &array_split(&$in) {
$keys = func_get_args();
array_shift($keys);
$out = array();
foreach($keys as $key) {
if(isset($in[$key]))
$out[$key] = $in[$key];
else
$out[$key] = null;
unset($in[$key]);
}
return $out;
}
?>
Example:
<?php
$testin = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$testout =& array_split($testin, 'a', 'b', 'c');
print_r($testin);
print_r($testout);
?>
Will print:
Array
(
[d] => 4
)
Array
(
[a] => 1
[b] => 2
[c] => 3
)
Hope this helps anyone!
A comment on array_merge mentioned that array_splice is faster than array_merge for inserting values. This may be the case, but if your goal is instead to reindex a numeric array, array_values() is the function of choice. Performing the following functions in a 100,000-iteration loop gave me the following times: ($b is a 3-element array)
array_splice($b, count($b)) => 0.410652
$b = array_splice($b, 0) => 0.272513
array_splice($b, 3) => 0.26529
$b = array_merge($b) => 0.233582
$b = array_values($b) => 0.151298
Ever wounder what array_splice is doing to your references, then try this little script and see the output.
<?php
$a = "a";
$b = "b";
$c = "c";
$d = "d";
$arr = array();
$arr[] =& $a;
$arr[] =& $b;
$arr[] =& $c;
array_splice($arr,1,0,array($d));
$sec_arr = array();
$sec_arr[] =& $d;
array_splice($arr,1,0,$sec_arr);
$arr[0] = "test"; // should be $a
$arr[3] = "test2"; // should be $b
$arr[1] = "this be d?"; // should be $d
$arr[2] = "or this be d?"; // should be $d
var_dump($arr);
var_dump($a);
var_dump($b);
var_dump($d);
?>
The output will be (PHP 4.3.3):
array(5) {
[0]=>
&string(4) "test"
[1]=>
&string(10) "this be d?"
[2]=>
string(13) "or this be d?"
[3]=>
&string(5) "test2"
[4]=>
&string(1) "c"
}
string(4) "test"
string(5) "test2"
string(10) "this be d?"
So array_splice is reference safe, but you have to be careful about the generation of the replacement array.
have fun, cheers!
In PHP 4.3.10, at least, it seems that elements that are inserted as part of the replacement array are inserted BY REFERENCE (that is, as though with the =& rather than = assignment operation). So if your replacement array contains elements that references to variables that you can also access via other variable name, then this will be true of the elements in the final array too.
In particular, this means that it is safe to use array_splice() on arrays of objects, as you won't be creating copies of the objects (as it is so easy to do in PHP 4).
the following:
$input = [[5=>"richard=red"], [15=>"york=yellow"], [25=>"gave=green"], [30=>"battle=blue"], [35=>"in=indigo"], [40=>"vain=violet"]];
array_splice($input, 2, 0, [[10=>"of=orange"]]);
var_dump($input);
gives this:
array (size=7)
0 =>
array (size=1)
5 => string 'richard=red' (length=11)
1 =>
array (size=1)
15 => string 'york=yellow' (length=11)
2 =>
array (size=1)
10 => string 'of=orange' (length=9)
3 =>
array (size=1)
25 => string 'gave=green' (length=10)
4 =>
array (size=1)
30 => string 'battle=blue' (length=11)
5 =>
array (size=1)
35 => string 'in=indigo' (length=9)
6 =>
array (size=1)
40 => string 'vain=violet' (length=11)
I need <?php array_Splice()?> function, that use array keys instead of order (offset and length) because of associated arrays, and this is result:
<?php
/**
* first variation
*
* $input is input array
* $start is index of slice begin
* $end is index of slice end, if this is null, $replacement will be inserted (in the same way as original array_Slice())
*indexes of $replacement are preserved in both examples
*/
function array_KSplice1(&$input, $start, $end=null, $replacement=null)
{
$keys=array_Keys($input);
$values=array_Values($input);
if($replacement!==null)
{
$replacement=(array)$replacement;
$rKeys=array_Keys($replacement);
$rValues=array_Values($replacement);
}
$start=array_Search($start,$keys,true);
if($start===false)
return false;
if($end!==null)
{
$end=array_Search($end,$keys,true);
// if $end not found, exit
if($end===false)
return false;
// if $end is before $start, exit
if($end<$start)
return false;
// index to length
$end-=$start-1;
}
// optional arguments
if($replacement!==null)
{
array_Splice($keys,$start,$end,$rKeys);
array_Splice($values,$start,$end,$rValues);
}
else
{
array_Splice($keys,$start,$end);
array_Splice($values,$start,$end);
}
$input=array_Combine($keys,$values);
return $input;
}
/**
* second variation
*
* $input is input array
* $start is index of slice begin
* $length is length of slice, what will be replaced, if is zero, $replacement will be inserted (in the same way as original array_Slice())
*/
function array_KSplice2(&$input, $start, $length=0, $replacement=null)
{
$keys=array_Keys($input);
$values=array_Values($input);
if($replacement!==null)
{
$replacement=(array)$replacement;
$rKeys=array_Keys($replacement);
$rValues=array_Values($replacement);
}
$start=array_Search($start,$keys,true);
if($start===false)
return false;
// optional arguments
if($replacement!==null)
{
array_Splice($keys,$start,$length,$rKeys);
array_Splice($values,$start,$length,$rValues);
}
else
{
array_Splice($keys,$start,$length);
array_Splice($values,$start,$length);
}
$input=array_Combine($keys,$values);
return $input;
}
$array=range(1,10);
var_Dump(array_KSplice1($array,3,3,array(100=>101,102,103,104)));
$array=range(1,10);
var_Dump(array_KSplice2($array,3,3,array(100=>101,102,103,104)));
?>
Both examples output:
array(11) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[100]=>
int(101)
[101]=>
int(102)
[102]=>
int(103)
[103]=>
int(104)
[6]=>
int(7)
[7]=>
int(8)
[8]=>
int(9)
[9]=>
int(10)
}
to kokos@lac.lviv.ua:
Good point about the code not doing what you expected.
The failure to check for the insert case like you pointed out is not a bug, however. I didn't add code to handle that because the key of such an added index is more or less undefined in an unordered associative array. Put another way, if your array is associative and not auto-indexed, you most likely care enough about your keys to want to set them explicitly.