Last active
June 2, 2019 21:05
-
-
Save Alexander-Pop/52dad0e9b2da0d642c8dac2da3112337 to your computer and use it in GitHub Desktop.
PHP - Move one element before another in an associative array
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function moveArrayKeyBefore($arr, $find, $move) { | |
if (!isset($arr[$find], $arr[$move])) { | |
return $arr; | |
} | |
$elem = [$move=>$arr[$move]]; // cache the element to be moved | |
$start = array_splice($arr, 0, array_search($find, array_keys($arr))); | |
unset($start[$move]); // only important if $move is in $start | |
return $start + $elem + $arr; | |
} | |
$arr = ['foo1'=>'fooel1', 'foo2'=>'fooel2', 'foo3'=>'fooel1']; | |
var_export(moveArrayKeyBefore($arr, 'foo3', 'foo1')); | |
?> | |
Output: | |
array ( | |
'foo2' => 'fooel2', | |
'foo1' => 'fooel1', | |
'foo3' => 'fooel3', | |
) | |
Explanation: | |
First check that both of the nominated keys exist in the array, if not return the input array untouched. isset() is very fast, certainly faster than in_array(). Furthermore, the !isset() check will require both keys to exist otherwise the early return will be triggered. This is as fast as this part gets. | |
Next, if both $find and $move exist in the array, my function will generate three array fragments: | |
$elem contains the associative array element declared by $move. | |
$start contains the elements that precede $find. array_search() returns the offset (numeric key) of the $find value in $arr. | |
$arr is modified by array_splice() and contains all elements from find to the end. | |
After the splice, when $move is in the $arr half, the union action bumps the duplicate element out. When $move is in the $start half, the convenient "bump" is lost, this means that the $move element needs to be removed from its original location. unset() can be used unconditionally because it doesn't error when the target element is not found. | |
https://codereview.stackexchange.com/questions/165263/move-one-element-before-another-in-an-associated-array |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Reorder a PHP array, moving items up or down | |
A quick set of functions to move items in a non-associative array | |
up or down by one, shifting the items around it appropriately. | |
Original usage was to for a set of UP and DOWN buttons to | |
manipulate the order of an array of items stored in Wordpress option. | |
*/ | |
$a = array('a','b','c','d','e'); | |
function down($a,$x) { | |
if( count($a)-1 > $x ) { | |
$b = array_slice($a,0,$x,true); | |
$b[] = $a[$x+1]; | |
$b[] = $a[$x]; | |
$b += array_slice($a,$x+2,count($a),true); | |
return($b); | |
} else { return $a; } | |
} | |
function up($a,$x) { | |
if( $x > 0 and $x < count($a) ) { | |
$b = array_slice($a,0,($x-1),true); | |
$b[] = $a[$x]; | |
$b[] = $a[$x-1]; | |
$b += array_slice($a,($x+1),count($a),true); | |
return($b); | |
} else { return $a; } | |
} | |
// Start | |
print_r($a); | |
/* Output | |
Array | |
( | |
[0] => a | |
[1] => b | |
[2] => c | |
[3] => d | |
[4] => e | |
) | |
*/ | |
// Move item 4 up | |
print_r(up($a,4)); | |
/* Output | |
Array | |
( | |
[0] => a | |
[1] => b | |
[2] => c | |
[3] => e | |
[4] => d | |
) | |
*/ | |
// Move item 0 down | |
print_r(down($a,0)); | |
/* Output | |
Array | |
( | |
[0] => b | |
[1] => a | |
[2] => c | |
[3] => d | |
[4] => e | |
) | |
*/ | |
// Test, move the bottom item down (ie. do nothing) | |
print_r(down($a,4)); | |
/* Output | |
Array | |
( | |
[0] => a | |
[1] => b | |
[2] => c | |
[3] => d | |
[4] => e | |
) | |
*/ | |
// Test, move the top item up (ie. do nothing) | |
print_r(up($a,0)); | |
/* Output | |
Array | |
( | |
[0] => a | |
[1] => b | |
[2] => c | |
[3] => d | |
[4] => e | |
) | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Adding item to array or change existent item position after shifting elements up or down depending on available positions | |
<?php | |
/** | |
* Author:Wajdi Jurry <[email protected]> (https://github.com/wajdijurry) | |
* Gist: https://gist.github.com/wajdijurry/a00752123134342ccc9d13a480c9f013 | |
*/ | |
class ArrayManipulation | |
{ | |
private $array; | |
public function __construct(array $array) | |
{ | |
$this->array = $array; | |
} | |
/** | |
* Add/Change item position in array | |
* Shifting elements up/down depending on available positions | |
* Priority for shifting down | |
* @param int $position | |
* @param string $itemId | |
* @return array | |
*/ | |
public function addItemChangePosition(int $position, string $itemId) | |
{ | |
$max = 5; // Max number of elements in array | |
if ($position >= $max || $poition < 0) { | |
exit('Wrong Position'); | |
} | |
// Remove item if exists | |
if (($key = array_search($itemId, $this->array)) !== false) { | |
unset($this->array[$key]); | |
} | |
$newArr = []; | |
if (array_key_exists($position, $this->array)) { | |
/** | |
* Determing shifting up or down | |
* Shifting up: 1, Shifting Down: -1 | |
*/ | |
$operator = (array_sum(array_keys($this->array)) >= array_sum(range($position, $max-1))) ? 1 : -1; | |
//Iterate over array, starting from $position till nonexistent element | |
for ($i = $position; $i >= $position * (-$operator); $i = $i - $operator) { | |
if (!array_key_exists($i, $this->array)) { | |
// Exit loop if element does not exist | |
break; | |
} | |
// Add items-to be shifted to $newArr | |
$newArr[$i - $operator] = $this->array[$i]; | |
// Remove from original array (avoiding duplicate) | |
unset($this->array[$i]); | |
} | |
// Merging shifted elements with non-affected elements, keys preserved | |
$this->array = $newArr + array_diff($this->array, $newArr); | |
} | |
// Add new item to array | |
$this->array[$position] = $itemId; | |
// Sort array | |
ksort($this->array, SORT_NUMERIC); | |
return $this->array; | |
} | |
} | |
// Example 1: | |
$items = [ | |
0 => 'item1', | |
1 => 'item2' | |
]; | |
print_r($items = (new ArrayManipulation($items))->addItemChangePosition(1, 'new item')); // $items = [0 => 'item1', 1 => 'new item', 2 => 'item2'] | |
// Example 2: | |
$items = [ | |
0 => 'item1', | |
3 => 'item2' | |
]; | |
print_r($items = (new ArrayManipulation($items))->addItemChangePosition(3, 'new item')); // $items = [0 => 'item1', 3 => 'new item', 4 => 'item2'] | |
// Example 3: | |
$items = [ | |
1 => 'item1', | |
2 => 'item2', | |
3 => 'item3', | |
4 => 'item4' | |
]; | |
print_r($items = (new ArrayManipulation($items))->addItemChangePosition(4, 'new item')); // $items = [0 => 'item1', 1 => 'item2', 2 => 'item3', 3 => 'item4', 4 => 'new item'] | |
// Example 3: | |
$items = [ | |
1 => 'item1', | |
2 => 'item2', | |
3 => 'item3', | |
4 => 'item4' | |
]; | |
print_r($items = (new ArrayManipulation($items, ))->addItemChangePosition(2, 'item4')); // $items = [1 => 'item1', 2 => 'item4', 3 => 'item2', 4 => 'item3'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment