Lets say I have this array:
$array = array(\'a\'=>1,\'z\'=>2,\'d\'=>4);
Later in the script, I want to add the value \'c\'=>3<
An alternative approach is to supplement the associative array structure with an ordered index that determines the iterative order of keys. For instance:
$index = array('a','b','d');
// Add new value and update index
$array['c'] = 3;
array_splice($index, 2, 0, 'c');
// Iterate the array in order
foreach $index as $key {
$value = $array[$key];
}
Try this
$array['c']=3;
An associative array is not ordered by default, but if you wanted to sort them alphabetically you could use ksort()
to sort the array by it's key.
If you check out the PHP article for ksort()
you will se it's easy to sort an array by its key, for example:
<?php
$fruits = array("d"=>"lemon", "a"=>"orange", "b"=>"banana", "c"=>"apple");
ksort($fruits);
foreach ($fruits as $key => $val) {
echo "$key = $val\n";
}
?>
// The above example will output:
a = orange
b = banana
c = apple
d = lemon
You can define your own sortmap when doing a bubble-sort by key. It's probably not terribly efficient but it works.
<pre>
<?php
$array = array('a'=>1,'z'=>2,'d'=>4);
$array['c'] = 3;
print_r( $array );
uksort( $array, 'sorter' );
print_r( $array );
function sorter( $a, $b )
{
static $ordinality = array(
'a' => 1
, 'c' => 2
, 'z' => 3
, 'd' => 4
);
return $ordinality[$a] - $ordinality[$b];
}
?>
</pre>
Here's an approach based on ArrayObject using this same concept
$array = new CitizenArray( array('a'=>1,'z'=>2,'d'=>4) );
$array['c'] = 3;
foreach ( $array as $key => $value )
{
echo "$key: $value <br>";
}
class CitizenArray extends ArrayObject
{
static protected $ordinality = array(
'a' => 1
, 'c' => 2
, 'z' => 3
, 'd' => 4
);
function offsetSet( $key, $value )
{
parent::offsetSet( $key, $value );
$this->uksort( array( $this, 'sorter' ) );
}
function sorter( $a, $b )
{
return self::$ordinality[$a] - self::$ordinality[$b];
}
}
Am I missing something?
$key = 'z';
$offset = array_search($key, array_keys($array));
$result = array_merge
(
array_slice($array, 0, $offset),
array('c' => 3),
array_slice($array, $offset, null)
);
Handling of nonexistent keys (appending $data
by default):
function insertBeforeKey($array, $key, $data = null)
{
if (($offset = array_search($key, array_keys($array))) === false) // if the key doesn't exist
{
$offset = 0; // should we prepend $array with $data?
$offset = count($array); // or should we append $array with $data? lets pick this one...
}
return array_merge(array_slice($array, 0, $offset), (array) $data, array_slice($array, $offset));
}
Demo:
$array = array('a' => 1, 'z' => 2, 'd' => 4);
// array(4) { ["a"]=> int(1) ["c"]=> int(3) ["z"]=> int(2) ["d"]=> int(4) }
var_dump(insertBeforeKey($array, 'z', array('c' => 3)));
// array(4) { ["a"]=> int(1) ["z"]=> int(2) ["d"]=> int(4) ["c"]=> int(3) }
var_dump(insertBeforeKey($array, 'y', array('c' => 3)));
For the moment the best i can found to try to minimize the creation of new arrays are these two functions :
the first one try to replace value into the original array and the second one return a new array.
// replace value into the original array
function insert_key_before_inplace(&$base, $beforeKey, $newKey, $value) {
$index = 0;
foreach($base as $key => $val) {
if ($key==$beforeKey) break;
$index++;
}
$end = array_splice($base, $index, count($base)-$index);
$base[$newKey] = $value;
foreach($end as $key => $val) $base[$key] = $val;
}
$array = array('a'=>1,'z'=>2,'d'=>4);
insert_key_before_inplace($array, 'z', 'c', 3);
var_export($array); // array ( 'a' => 1, 'c' => 3, 'z' => 2, 'd' => 4, )
// create new array
function insert_key_before($base, $beforeKey, $newKey, $value) {
$index = 0;
foreach($base as $key => $val) {
if ($key==$beforeKey) break;
$index++;
}
$end = array_splice($base, $index, count($base)-$index);
$base[$newKey] = $value;
return $base+$end;
}
$array = array('a'=>1,'z'=>2,'d'=>4);
$newArray=insert_key_before($array, 'z', 'c', 3);
var_export($array); // ( 'a' => 1, 'z' => 2, 'd' => 4, )
var_export($newArray); // array ( 'a' => 1, 'c' => 3, 'z' => 2, 'd' => 4, )
A simplified Alix Axel function if you need to just insert data in nth position:
function array_middle_push( array $array, int $position, array $data ): array {
return array_merge( array_slice( $array, 0, $position ), $data, array_slice( $array, $position ) );
}