Skip to content

Instantly share code, notes, and snippets.

@hjc
Last active October 2, 2015 01:57
Show Gist options
  • Save hjc/2148747 to your computer and use it in GitHub Desktop.
Save hjc/2148747 to your computer and use it in GitHub Desktop.
PHP: Add a key to an associative array and keep it's key ordering intact and sequential
/**
* Implements add_to_assoc_numeric
*
* Goal of this function is to allow us to modify an associative, numeric array
* (one that uses string numbers as keys, so there is no 0,1,2,3 ordering, but
* rather the ordering is based on when the keys were inserted [they are treated
* like other string keys]). If we modify this array using array_unshift or
* array_shift, we destory this associative, numeric structure (each key is
* destroyed and the array is simply renumbered, with ints, from 0 to num_elems),
* which we don't want. This function will allow us to insert a new value anywhere
* in the string and order it correctly, as long as we want consecutive ordering
* (why wouldn't we?).
*
* Example, our array ($animals) is:
* '4' => 'Dog',
* '5' => 'Cat',
* '8' => 'Racoon',
*
* And we want to add in 'Mouse' to position '3' (because its our third favorite
* animal, for example). Using: $animals['3'] will make the array structure:
* '4' => 'Dog',
* '5' => 'Cat',
* '8' => 'Racoon',
* '3' => 'Mouse',
*
* Which we don't want because it misorders select lists, using this function would
* give us:
* '3' => 'Mouse',
* '4' => 'Dog',
* '5' => 'Cat',
* '8' => 'Racoon',
* Keeping the order of our lists correct!
*
* String is expected to be fully numeric (odd behavior can occur elsewise).
*
* Has bonus benefit of sorting an unsorted associative array that uses numeric
* string keys. Since sorting in associative arrays is based on when the elements
* were inserted, they can get out of order quickly. This function naturally
* sorts them
*
* @param &$assoc
* Array keyed with sequential, numeric string keys. We want to add a new value
* into this array in a specified position, but we want to keep this array's
* current structure. Will not be returned, but rather altered by reference
*
* @param $new_pos
* The position where we want the new element to go in. This position will then
* be placed in the correct order in the array. Example, we have these keys:
* 0, 1, 4, 5 and want to add key 3 which is passed in as $new_pos. This function
* lets us make an array with this key ordering: 0, 1, 3, 4, 5 and not: 0, 1, 4, 5, 3
*
* @param $new_val
* The new value we want to put in the position/key specified by $new_pos
*
* @return &$assoc
* No real return, the contents of the passed in array are changed by reference
* due to the array's passing method.
*/
function add_to_assoc_numeric(&$assoc, $new_pos, $new_val = NULL) {
// Declare new array to hold new element + old in correct order
$new_assoc = array();
// Get a list of the arrays keys
$keys = array_keys($assoc);
//sort keys for faster iteration
sort($keys);
//store size of keys array
$keys_size = count($keys);
// Get max key for bounds
$min = $keys[0];
//Get min key for bounds
$max = $keys[$keys_size - 1];
//set iterator
$place = 0;
//See if new position is greater than our current minimum, if so we have
//to populate the intermediary values, otherwise there are none
if ($new_pos > $min)
{
//Populate values between $min and $new_pos
for (; $keys[$place] < $new_pos; $place++) {
//Cast to string to get right key
$new_assoc[(string)$keys[$place]] = $assoc[(string)$keys[$place]];
}
}
//Add new value in its position, perfectly placing it in order
$new_assoc[(string)$new_pos] = $new_val;
//Add remaining elements of array, if new position is greater than greatest
//current key, for loop is skipped
for (; $place < $keys_size; $place++) {
$new_assoc[(string)$keys[$place]] = $assoc[(string) $keys[$place]];
}
//Set $assoc to $new_assoc to change array
$assoc = $new_assoc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment