I have a post array and need to create a new array format from this to store in database with batch insert. I have achieved it with the following code. But want a better solution (if any) to achieve my array. I wanted to eliminate the inner loop but did not get any solution. Please provide any suggestion on how can I achieve this.
Code to parse array:
if ($this->input->post()) {
foreach ($this->input->post() as $key => $value) {
$i = 0;
/* need to eliminate this loop */
foreach ($value as $k => $v) {
$postData[$i][$key] = $v;
$i++;
}
}
}
Input array:
Array
(
[category_id] => Array
(
[0] => 1
[1] => 4
)
[pay_type_id] => Array
(
[0] => 2
[1] => 5
)
[frequency_id] => Array
(
[0] => 3
[1] => 6
)
)
Output array;
Array
(
[0] => Array
(
[category_id] => 1
[pay_type_id] => 2
[frequency_id] => 3
)
[1] => Array
(
[category_id] => 4
[pay_type_id] => 5
[frequency_id] => 6
)
)
Because you have two arrays, a:"records" and b:"fields" in any case, theoretically, you need to have at least two loops to populate the "records" and "fields" inside a record. And, basically, this is not a bad approach or a problem.
If you really want just one loop, because of faith reasons, you need to put a hard-coded list of field assignments in first loop that populate the records.
The only way I can see to do it without a second array is like this:
$arr = array("category_id" => array(1, 4), "pay_type_id" => array(2, 5), "frequency_id" => array(3, 6));
foreach ($arr as $key => $value) {
$postData[0][$key] = $value[0];
$postData[1][$key] = $value[1];
}
print_r($postData);
But you lose flexibility with this approach, because you have to know in advance how many indexes there will be in the inner arrays. The only way to make it generic enough to cope with changes in data is to use an inner loop similar to how you did it originally.
There's nothing much wrong with your original code, it's a pretty standard and reasonable approach to changing the array format in this scenario. It shouldn't give you any particular performance issues, even with fairly large arrays, and there's not really any neater way to approach it.
As per your ouput you need second loop also. But yes you can eliminate use of $i
you can use $k
instead. You can change your code as:
if ($this->input->post()) {
foreach ($this->input->post() as $key => $value) {
foreach ($value as $k => $v) {
$postData[$k][$key] = $v;
}
}
}
If you really want to, you can do this without loops at all:
$input = $this->input->post();
$keys = array_keys($input);
$postData = [
array_combine($keys, array_column($input, 0)),
array_combine($keys, array_column($input, 1)),
];
This will give the same $postData
output as your example, assuming that the input only has keys 0
and 1
in the inner arrays, as it does in your example. If the number of possible elements in the inner arrays is unknown, then you may need to introduce a loop on that, but the secondary loop can still be avoided.
I had to use array_combine()
as well as array_column()
as array_column()
on it's own does not preserve the named keys the your top level of your array.
Other solutions using array_map()
or array_walk()
may also exist.
However, while it's short and concise, it isn't exactly clear for a reader to understand what it's doing, so unless you document it clearly, you'll be creating a maintenance headache for yourself in the long term.
The double-loop is a more readily understandable solution, pretty standard, and won't cause you any issues. So while I've given you a solution, I would actually recommend just using the code you've got.