Given an integer $value
in the range of 1, 2, 3
, I want to get an array that starts with $value
and proceeds with the remaining two integers from above in arbitrary order. The best I could think of was doing something like this:
switch ($value) {
case '1':
$array = [1,2,3];
break;
case '2':
$array = [2,1,3];
break;
case '3':
$array = [3,1,2];
break;
}
Is there a shorter and more beautiful way of doing that? Something like that:
$array = push_to_top_of_array($value,[1,2,3]);
4 Answers 4
Is there a shorter and more beautiful way of doing that?
- shorter: yes
- more beautiful: well, that sounds subjective... you can be the judge of the approaches below.
One approach would be to take off the value using $index
with array_splice()
and then put it (the first element from that spliced array) at the beginning using array_unshift()
:
$array = [1, 2, 3];
array_unshift($array, array_splice($array, $value - 1, 1)[0]);
See it demonstrated in this playground example.
Another approach would be to merge the spliced array and the original array using array_merge()
:
$array = [1, 2, 3];
$array = array_merge(array_splice($array, $value - 1, 1), $array);
See it demonstrated in this playground example.
Yes, for three array elements you can write:
$arr = [
($value - 1) % 3 + 1,
($value + 0) % 3 + 1,
($value + 1) % 3 + 1
];
The main ingredient here is the $value modulo 3
expression. The above code contains some redundancies, which I have kept to clearly show the construction of the code. If you absolutely need faster code instead of readable code, the above is equivalent to:
$arr = [
$value,
$value % 3 + 1,
5 - $value - $value % 3
];
Or, the brute force variant:
// To be executed only once in the program.
$arrs = [[], [1, 2, 3], [2, 3, 1], [3, 1, 2]];
// And then, whenever you need it:
$arr = $arrs[$value];
I hate hardcoded solutions and prefer generalized ones. You never know when your array will get a 4th element and break all the application.
So a generalized solution would be like
- get a key for the desired value
- remove this element from array
- add its value to the beginning of an array
in PHP it would be like
function push_to_top_of_array($value, $array) {
$key = array_search($value, $array);
if ($key === false) {
throw new \OutOfRangeException("Value not found");
}
unset($array[$key]);
array_unshift($array, $value);
return $array;
}
$value = 2;
$array = [3, 5, 2, 4];
$array = push_to_top_of_array($value, $array);
I'm not sure if "more beautiful" means you want a one-liner, but here are two more concise ways to perform the task:
*note, this doesn't validate the $value
as being one of the element values -- if this is a necessary component of your project, then please clarify in your question.
Code: (Demo)
$value = 2;
$array = [1, 2, 3];
array_unshift($array,$value); // prepend a duplicate
var_export(array_unique($array)); // kill the original
echo "\n---\n";
$value = 2;
$array = [1, 2, 3];
var_export(array_unique(array_merge([$value],$array))); // prepend a duplicate, kill the original
Output:
array (
0 => 2,
1 => 1,
3 => 3,
)
---
array (
0 => 2,
1 => 1,
3 => 3,
)
On huge arrays, statistics have shown array_flip(array_flip())
out performs array_unique()
but that would certainly be less beautiful and if you were dealing with big array I'm sure you would have mentioned that.
$array
used after this code? would there ever be a case where other values would exist in that array? \$\endgroup\$foreach
loop. There is no case where other values would exist. \$\endgroup\$foreach
loop do with it? Can you describe the output of the script? For code review, it is best to have a broad picture of what the code does. \$\endgroup\$