Eliminate PHP Loop - php

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
)
)

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.

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;
}
}
}
DEMO

Related

Get the multidimensional array index value corresponding to other array values

I've a PHP multidimensional array like:
array(
[0] => array("code"=>code1, "value"=>val1, "operation"=>Add),
[1] => array("code"=>code2, "value"=>val2, "operation"=>Remove),
[2] => array("code"=>code3, "value"=>val3, "operation"=>Edit)
)
If I know code and value, how can I get the operation array index value corresponding to that entry. Eg: If I pass code1 and val1, then it should return the value Add. I can use foreach(), but I'm looking for some other faster and efficient way to get it.
Can anyone help me? Thanks in advance.
Simple foreach with a break/return when found will be O(n) in worst case, O(1) in best.
Modifying source array as:
array(
'code1:val1' => Add,
'code2:val2' => Remove,
'code3:val3' => Edit
)
will give you O(1) with accessing like $arr['code1:val1'].
Solution, for example, with array_filter will be O(n) always.
just run a foreach. It will be an O(n) search on worst case.
function getOperation($code,$value){
foreach($array as $key => $item){
if($item["code"]===$code && $item["value"] === $value)
return $item["operation"];
}
return;
}

Get value from different arrays

I'm getting started with PHP and I have some troubles finding a way to output values from multiples arrays sent from an external site.
I did a foreach and the code that is printed looks like this :
Array
(
[id] => 1
[title] => Title 1
)
Array
(
[id] => 2
[title] => Title 2
)
Array
(
[id] => 3
[title] => Title 3
)
Any idea how I could get every id (1,2,3) in an echo?
Let me know if you need more informations!
Thanks a lot!
If you just want to echo all the id's in all the arrays, a simple solution would be:
foreach ([$array1, $array2, $array3] as $arr) {
echo $arr['id'];
}
A better solution would probably to create one main array first:
$mainArray = [];
and every time you get a new array, you just push them to the main array:
$mainArray[] = $array1;
$mainArray[] = $array2;
// ... and so on
Then you'll have a multi dimensional array and can loop them with:
foreach ($mainArray as $arr) {
echo $arr['id'];
}
Which solution that works best depends on how you get the arrays and how many they are.
Note: Using array_merge() as others have suggested will not work in this case, since all the arrays have the same keys. From the documentation on array_merge(): "If the input arrays have the same string keys, then the later value for that key will overwrite the previous one."
As you can do:
$array = array_merge_recursive($arr1, $arr2, $arr3);
var_dump($newArray['id']);
echo implode(",", $newArray['id']);
A demo code is here

Checking uri segment

I want to check if uri segment($sef) is in array, before sending id to database.
And I want to ask which solution is better, or if is there something better.
Here are examples of how I tried to search the array
1)
if(array_search($sef, array_column($array,'sef'))) {
//find id and send it to DB
} else {
//wrong sef
}
2)
foreach($array as $k => $v) {
if( in_array($sef, $v)) {
return $v['id']; break;
} else {
//wrong sef
}
}
this is example of array
Array
(
[0] => Array
(
[sef] =>some-sef1
[id] => 39
)
[1] => Array
(
[sef] => some-sef2
[id] => 20
)
[2] => Array
(
[sef] => some-sef3
[id] => 38
)
Thanks for answers!
It depends on situation. For small size array, both of them will almost take same time.
1) If it's a small array, you can do it using in_array.
2) If it's a large array, You should use first one. Because a foreach will take more time to execute than array_search.
Both ways are almost the same, so it's a preference choice.
There are some tweaks possible though. First:
$sef_ids = array_column($array, 'id', 'sef');
if (isset($sef_ids[$sef])) { $id = $sef_ids[$sef]; ... }
Second:
foreach ($array as $k => $v) {
if ($v['sef'] === $sef) { $id = $v['id']; ... }
}
Now first one looks faster (didn't check), but it's still micro optimization unless you work with large arrays. I would aim for having $sef_ids data structure to work with from the beginning then.

I stuck on read sub-arrays

I have an array with different first indexes.
Now, I want to read all client_created strings without using $array[688]["client_created"], $array[690]["client_created"] ...
How can I read all these client_created strings without using these numbers like 688, 690, 695, 700 etc.?
This is how it looks like:
Array
(
[688] => Array
(
[client_created] => 1393324278
)
[690] => Array
(
[client_created] => 1393440457
)
)
That was only 2 examples, in practice, I have over 500 items.
Foreach will parse over the entire array.
foreach($myarray as $index=>$subarray)
echo $subarray['client_created']."\n";
Probably best for you would be to catch all those strings through foreach:
$values=array();
foreach($yourArray as $index => $clientCreatedArray)
{
$values[] = $clientcreatedArray["client_created"];
}
Let me know if this works for you.

Two PHP arrays, unset positions that are only present in one array

I have two arrays (in PHP):
ArrayA
(
[0] => 9
[1] => 1
[2] => 2
[3] => 7
)
ArrayB
(
[0] => 1
[1] => 1
[3] => 8
)
I want to make two new arrays, where I have only the elements declared in both of the arrays, like the following:
ArrayA
(
[0] => 9
[1] => 1
[3] => 7
)
ArrayB
(
[0] => 1
[1] => 1
[3] => 8
)
In this example ArrayA[2] doesn't exist, so ArrayB[2] has been unset.
I wrote this for loop:
for ($i = 0, $i = 99999, $i++){
if (isset($ArrayA[$i]) AND isset($ArrayB[$i]) == FALSE)
{
unset($ArrayA[$i],$ArrayB[$i]);
}
}
But it's not great because it tries every index between 0 and a very big number (99999 in this case). How can I improve my code?
The function you're looking for is array_intersect_key:
array_intersect_key() returns an array containing all the entries of array1 which have keys that are present in all the arguments.
Since you want both arrays, you'll have to run it twice, with the parameters in opposite orders, as it only keeps keys from the first array. An example:
$arrayA_filtered = array_intersect_key($arrayA, $arrayB);
$arrayB_filtered = array_intersect_key($arrayB, $arrayA);
Also, although a for loop wasn't ideal in this case, in other cases where you find yourself needing to loop through sparse array (one where not every number is set), you can use a foreach loop:
foreach($array as $key => $value) {
//Do stuff
}
One very important thing to note about PHP arrays is that they are associative. You can't simply use a for loop, as the indices are not necessarily a range of integers. Consider what would happen if you applied this algorithm twice! You'd get out of bounds errors as $arrayA[2] and $arrayB[2] no longer exist!
I would iterate through the arrays using nested foreach statements. I.e.
$outputA = array();
$outputB = array();
foreach ($arrayA as $keyA => $itemA) {
foreach ($arrayB as $keyB => $itemB) {
if ($keyA == $keyB) {
$outputA[$keyA] = $itemA;
$outputB[$keyB] = $itemB;
}
}
This should give you two arrays, $outputA and $outputB, which look just like $arrayA and $arrayB, except they only include key=>value pairs if the key was present in both original arrays.
foreach($arrayA as $k=>$a)
if (!isset($arrayB[$k]))
unset($arrayA[$k];
Take a look to php : array_diff
http://docs.php.net/manual/fr/function.array-diff.php

Categories