4
\$\begingroup\$

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]);
\$\endgroup\$
  • \$\begingroup\$ I should have asked earlier... how is $array used after this code? would there ever be a case where other values would exist in that array? \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ May 31 '18 at 15:00
  • \$\begingroup\$ @SamOnela the array goes through a foreach loop. There is no case where other values would exist. \$\endgroup\$ – Adam May 31 '18 at 15:49
  • \$\begingroup\$ Okay- what does the 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\$ – Sᴀᴍ Onᴇᴌᴀ May 31 '18 at 15:50
7
\$\begingroup\$

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.

\$\endgroup\$
6
\$\begingroup\$

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];
\$\endgroup\$
5
\$\begingroup\$

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);
\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.