-5
\$\begingroup\$

I have two closely related questions:

1) I have a mixed PHP array. Not mixed in that it contains strings, floats, booleans etc. but mixed in that it is a hybrid indexed / associative array. Most of its entries look like they are from an indexed array while the very last entry looks like it's from an associative array:

$myFruit = [
  'apple',
  'banana',
  'cherry',
  'Other_Fruit' => ['Damson', 'Elderberry', 'Fig', 'Grapefruit']
];

It strikes me that this is a bad idea, but I need to confirm that first... Is it a bad idea to have an array in PHP which is a hybrid between an indexed array and an associative array? Or is this not entirely uncommon practice in PHP?

2) If it is a bad idea (as I suspect), what is the best way to tidy it up, given that I want to preserve the entry ['Other_Fruit'] exactly as it is.

At present I am using the following:


Code to Review:

$myFruit2 = [];
$myFruit2['Fruitbowl'] = $myFruit;
$myFruit2['Other_Fruit'] = $myFruit2['Fruitbowl']['Other_Fruit'];
unset($myFruit2['Fruitbowl']['Other_Fruit']);
$myFruit = $myFruit2;

This leaves me with:

$myFruit = [
  'Fruitbowl' => ['apple', 'banana', 'cherry'],
  'Other_Fruit' => ['Damson', 'Elderberry', 'Fig', 'Grapefruit']
];

which is exactly what I want... only I'm not sure I'm getting there the most efficient / fastest / best practice way.

Ultimately, I am looking to maximise speed, efficiency and process optimisation and minimise garbage collection or other processes which might slow the operation down. I want to tidy up the array as quickly as possible. I am uncertain, for example, if there are any (much faster) native functions that I ought to be using instead.

(Subsequent thought: Maybe I can achieve this via destructuring...?)


Addendum:

If I understand correctly, some users are objecting to the fact that in my code to be reviewed (above), I have used example variable names above instead of the actual variable names I am using.

I cannot comprehend the nature of this objection, but nevertheless, in response to it, here is the example (again):

$myFruit2 = [];
$myFruit2['Fruitbowl'] = $myFruit;
$myFruit2['Other_Fruit'] = $myFruit2['Fruitbowl']['Other_Fruit'];
unset($myFruit2['Fruitbowl']['Other_Fruit']);
$myFruit = $myFruit2;

And here is the actual code:

$Codesheets = [];
$Codesheets['Static'] = $moduleBlock['Codesheets'];
$Codesheets['Dynamic'] = $moduleBlock['Static']['Dynamic'];
unset($Codesheets['Static']['Dynamic']);
$moduleBlock['Codesheets'] = $Codesheets;

It will be apparent that the example I gave above is a 1:1 representation of the actual code.

\$\endgroup\$
11
  • 1
    \$\begingroup\$ Reason off-topic: Pseudocode, stub code, hypothetical code, obfuscated code, and generic best practices are outside the scope of this site. You have provided generic data and asking for general best practice. \$\endgroup\$ Feb 29, 2020 at 0:39
  • 1
    \$\begingroup\$ How can anyone propose to accurately advise on "maximise speed, efficiency and process optimisation and minimise garbage collection or other processes which might slow the operation down" when you haven't shown realistic sample data nor how you intend to process it? \$\endgroup\$ Feb 29, 2020 at 1:01
  • 1
    \$\begingroup\$ Providing clear sample data is one requirement here. A missing requirement is how you intend to use the data. The fact that you are satisfied by slepic's answer is not a factor in deciding if your question is on-topic. How can anyone confidently advise on the best data structure if we don't know how it will be used. \$\endgroup\$ Mar 1, 2020 at 8:49
  • 4
    \$\begingroup\$ This is where you are failing to understand my motivations. I am not here to put anyone down, I am here to help CodeReview up. Data structures are best designed by considering how the data will be used. You are taking offense to my feedback, but what you should do is pay attention to what I am asking for and improve your question by telling us all the ways you intend to use the data. \$\endgroup\$ Mar 1, 2020 at 9:06
  • 1
    \$\begingroup\$ I've reviewed enough code to know that foo/bar and other bogus-names "my real code is just like it", never, never, never ends well. Reviewers aren't here to answer specific questions about best practices illustrated with sample code, they're here to review real, working code with a purpose, and tell you if best practices are taking a beating. The difference, is that in that latter scenario, the code to be reviewed becomes central, not just an illustration of a situation encountered in code that needs an "answer" - CR doesn't do "answers", we do reviews. \$\endgroup\$ Mar 2, 2020 at 17:46

3 Answers 3

3
\$\begingroup\$

It is often not very useful to have such a mix. It could make sense if you really wanted it to be associative array, but it just so happens that you can have the key strings contain numbers and even consecutive numers starting at zero which make it look like vector because php converts integer string keys to ints.

For example:

$robotsByName = [
  "0" => ["id" => 0, "name" => "0"],
  "1" => ["id" => 1, "name" => "1"],
  "2" => ["id" => 2, "name" => "2"],
  "johnny5" => ["id" => 3, "name" => "johnny5"],
];

If you have to deal with the input structure as is because it is not under your control, you could simplify your conversion like this:

$myFruit = [
  'Fruitbowl' => \array_slice($myFruit, 0, \count($myFruit)-1),
  'Other_Fruit' => $myFruit['Other_Fruit'],
];
\$\endgroup\$
1
  • 1
    \$\begingroup\$ array_slice() - perfect. Thank you. Also you've introduced me to PHP Namespacing. \$\endgroup\$
    – Rounin
    Feb 28, 2020 at 10:15
3
\$\begingroup\$

What you are doing here is denoting metadata about the fruit entries through the data structure. If it works for you then it’s certainly an acceptable solution. However, it will make the code much more readable and meaningful if you can get that metadata out of the structure and represent it directly. Someone unfamiliar with it (which might well be you a few months from now :)) is going to be able to figure out what everything means much more quickly.

To do that, you need to answer the question “what make fruit belong in the ‘other fruit’ array”? Making a guess based on the example data, is it a question of the ‘Other Fruit’ being less common?

If so, you could potentially use more meaningful names in your example last array.

$myFruit = [
 'common' => [
    'apple',
    'banana',
    'cherry',
 ],
'rare' => [
    'Damson',
    'Elderberry',
    'Fig',
    'Grapefruit',
 ],
];

A few notes in comparing this with what you have:

  1. array() and [] do the exact same thing and are interchangeable. There is no reason to use array() at the very top level.
  2. Doing array([‘Fruitbowl’] => […]) make the key an array, which I don’t think you want. Rather, you likely want array(‘Fruitbowl’=>[…]), which is the same as [‘fruitbowl’ => […]]

All of this said, any multidimensional array is a good opportunity to think about writing a class to represent the data and incorporate an object. Something to keep in mind if any more complexity creeps into this array.

\$\endgroup\$
1
  • \$\begingroup\$ My apologies, I didn't make it sufficiently clear which part of my question was the Code to Review. I have edited the question to indicate it much more clearly. To restate my two questions: 1) Is a hybrid associative / indexed array a bad idea; and 2) what is the best approach to transform the former into a "non-mixed" associative (or even an indexed) array? \$\endgroup\$
    – Rounin
    Feb 27, 2020 at 23:38
-1
\$\begingroup\$

Aha. Cracked it.

What I was looking for ultimately wasn't so much destructuring, but might be termed "restructuring".

Input:

$myFruit = [
  'apple',
  'banana',
  'cherry',
  'Other_Fruit' => ['Damson', 'Elderberry', 'Fig', 'Grapefruit']
];

Operation:

$myFruit = [
  'Fruitbowl' => $myFruit,
  'Other_Fruit' => $myFruit['Other_Fruit']
];

unset($myFruit['Fruitbowl']['Other_Fruit']);

Output:

$myFruit = [
  'Fruitbowl' => ['apple', 'banana', 'cherry'],
  'Other_Fruit' => ['Damson', 'Elderberry', 'Fig', 'Grapefruit']
];
\$\endgroup\$
1
  • 3
    \$\begingroup\$ I don't see this post as a Review. \$\endgroup\$ Feb 29, 2020 at 1:02

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