Moving values from one array to another in PHP - php

I have tried doing this for a while and can't wrap my head around it. I have two arrays. One array that contains sensors information called $sendatas and another that contains where those sensors are allocated to called $zones.
I want to be able to create dynamic HTML checkboxes within a table row based on whether the sensor is allocated to a zone or not and if it is then show a checked checkbox and if it isn't then show an unchecked checkbox.
Here is an example of my arrays:
The $sendatas array:
[1] => Array
(
[hwserial] => 00002025
[name] => FG05 Room Temp
[serial] => 5
[chan] => 1
[alarmhigh] => 30
[alarmlow] => 5
[delay] => 10
)
[2] => Array
(
[hwserial] => 00002025 01
[name] => FG05 Kitchen 1 Freezer
[serial] => 5
[chan] => 2
[alarmhigh] => -10
[alarmlow] => -35
[delay] => 10
)
The $zones array:
[0] => Array
(
[serial] => 1
[idGrid] => 50
[name] => All Sensors
)
[1] => Array
(
[serial] => 1
[idGrid] => 52
[name] => Food Area
)
[2] => Array
(
[serial] => 2
[idGrid] => 50
[name] => All Sensors
)
[3] => Array
(
[serial] => 2
[idGrid] => 52
[name] => Food Area
)
[4] => Array
(
[serial] => 3
[idGrid] => 50
[name] => All Sensors
)
[5] => Array
(
[serial] => 3
[idGrid] => 52
[name] => Food Area
)
[6] => Array
(
[serial] => 4
[idGrid] => 50
[name] => All Sensors
)
Both of my zones are not the same length. What I want to be able to achieve is to create an array that looks like this by finding the serial keys that match from both arrays.
Array
(
[0] => Array
(
[hwserial] => 00001216
[name] => Fridge Office Thermal
[serial] => 1
[chan] => 1
[alarmhigh] => 8
[alarmlow] => -2
[delay] => 10
[idGrid1] => 50
[idGrid2] => 51
[idGrid3] => 52
[zonename1] => All Sensors
[zonename2] => Office
[zonename3] => Food Area
)
[1] => Array
(
[hwserial] => 00002025
[name] => FG05 Room Temp
[serial] => 5
[chan] => 1
[alarmhigh] => 30
[alarmlow] => 5
[delay] => 10
[idGrid] => 50
[idGrid] => Not Used
[idGrid] => 52
[zonename1] => All Sensors
[zonename2] => Not Used
[zonename3] => Food Area
)
I am pretty sure I can write the code for the checkboxes once I have this array formatted properly. I have tried using some foreach loops but just keep making a mess of it. I have so far tried this on and off for a few weeks hoping it would just come to me but it hasn't. Any help appreciated.

Based on what you said you're trying to do with this, I think it looks like the array you're trying to create will not be that easy to work with. I think your sensors array is fine, and you just need to focus on the $zones array.
foreach ($zones as $zone) {
$zones_sensors[$zone['idGrid']]['name'] = $zone['name'];
$zones_sensors[$zone['idGrid']]['sensors'][$zone['serial']] = true;
}
This will reorganize the data in your $zones array into this format:
$zones_sensors = [
50 => ['name' => 'All Sensors', 'sensors' => [1 => true, 2 => true, 3 => true]],
51 => ['name' => 'Office', 'sensors' => [1 => true]],
52 => ['name' => 'Food Area', 'sensors' => [1 => true, 2 => true, 3 => true]]
];
This provides the two things you need to output the checkboxes as you described.
A complete list of zones
An indexed collection of serials associated with each zone.
You can use it to output headers for all the zones
foreach ($zones_sensors as $zone_id => $zone) {
// output one row with headers for zones
echo $zone['name']; // (formatting up to you)
}
Then when you output the sensors it will be easy to find which zones they're allocated to.
foreach ($sendatas as $sensor) { // make a row for each sensor
foreach ($zones_sensors as $zone_id => $zone) { // iterate the full list of zones
// check if the sensor is allocated to that zone
if (isset($zone['sensors'][$sensor['serial']])) {
// checkbox is checked
} else {
// checkbox is unchecked
}
}
}

This should just be a matter of creating a new array (let's call it $combined) that is a clone of one of the $sendatas array but uses the [serial] as a key so that you can target specific item. You would loop through the $zones array and for each item check if the [serial] is found in $combo and if a match is found inject the [idgrid] and [name] as a sub array for $combined['serial']. As you have not used sub array you could add a counter to add an incrementing number of values.

Something along the lines of this should do the trick:
$results = [];
foreach ($sendatas as $sensor) {
$zone_counter = 0;
foreach ($zones as $zone) {
if ($zone['serial'] == $sensor['serial']) {
$zone_counter++;
$sensor['idGrid' . $zone_counter] = $zone['idGrid'];
$sensor['zonename' . $zone_counter] = $zone['name'];
}
}
$results[] = $sensor;
// if you only want $results to contain sensors that actually have zones,
// wrap it in an if-statement:
// if ($zone_counter > 0) {
// $results[] = $sensor;
// }
}
print_r($results);
Note that this won't give you any sensors with matching zones with the data you provided, because those two sensors both have [serial] => 5 and all your zones have [serial] => 1 through 4. If you want to match by some other key instead of serial, just change the if-statement.

Related

Using values in one associative array to test against values in another associative array

I need help, tried for days without successs, new to PHP so please forgive me, I have an associative Array below returned from a database table grading system, what I want to achieve is try "scores" from another associative array, iterate through the grading system until I find a score that falls between values in a row in the grading system then return the letter grade and remarks, see below what have tried, am exhausted, any help would be very appreciated.
code I have tried
while ($row = $grade->fetch(PDO::FETCH_ASSOC)) {
$data = $row;
var_export($data);
} //fetches the grading system whose array is seen below
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$scores = $row;
var_export($scores);
}// fetches scores of students in test
foreach($data as $key=> $grading) {
foreach($scores as $key =>$values){
if($values["marks"]>=$grading["grade_min"] && $values["marks"]<=$grading["grade_max"])
print_r($values["marks"]);
print_r($grading["grade"]);
print_r($grading["remarks"]);
}
} Am trying to iterate each scores against the grading system but not successful, please help.
Array
(
[0] => Array
(
[id] => 2
[grade_min] => 1
[grade_max] => 39
[grade] => E
[remarks] => Fail
)
[1] => Array
(
[id] => 3
[grade_min] => 40
[grade_max] => 49
[grade] => D
[remarks] => Pass
)
[2] => Array
(
[id] => 4
[grade_min] => 50
[grade_max] => 59
[grade] => C
[remarks] => Credit
)
[3] => Array
(
[id] => 5
[grade_min] => 60
[grade_max] => 69
[grade] => B
[remarks] => Good
)
[4] => Array
(
[id] => 6
[grade_min] => 70
[grade_max] => 79
[grade] => A
[remarks] => Very Good
)
[5] => Array
(
[id] => 7
[grade_min] => 80
[grade_max] => 100
[grade] => A+
[remarks] => Excellent
)
)
Array
(
[0] => Array
(
[id] => 2
[grade_min] => 1
[grade_max] => 39
[grade] => E
[remarks] => Fail
)
[1] => Array
(
[id] => 3
[grade_min] => 40
[grade_max] => 49
[grade] => D
[remarks] => Pass
)
[2] => Array
(
[id] => 4
[grade_min] => 50
[grade_max] => 59
[grade] => C
[remarks] => Credit
)
[3] => Array
(
[id] => 5
[grade_min] => 60
[grade_max] => 69
[grade] => B
[remarks] => Good
)
[4] => Array
(
[id] => 6
[grade_min] => 70
[grade_max] => 79
[grade] => A
[remarks] => Very Good
)
[5] => Array
(
[id] => 7
[grade_min] => 80
[grade_max] => 100
[grade] => A+
[remarks] => Excellent
)
)
Scores Array looks like this:
Array
(
[0] => 35
[1] => 48
[2] => 57
[3] => 78
[4] => 75
[5] => 89
)
I want to iterate these scores array against the grading system array and return only the "grade" and "remarks" that matched where the scores is between "grade_min" and "grade_max"
It's better to iterate over scores and then iterate grading to find the one that score belongs to.
Additionally, your if has no curly braces, so it will execute only the first sentence after it.
// fetches the grading system whose array is seen below
while ($row = $grade->fetch(PDO::FETCH_ASSOC)) {
$data = $row;
// var_export($data); // No need to se this anymore
}
// fetches scores of students in test
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$scores = $row;
// var_export($scores); // No need to see this anymore
}
// Iterate scores first (I don't know if you need the index or not)
foreach($scores as $scoreIndex => $score) {
// Search grading for this score (Index not needed here, just values)
foreach($data as $grading) {
if($score['marks'] >= $grading['grade_min'] && $score['marks'] <= $grading['grade_max']) {
// Score is inside this grading
// Echo, print or assign what you need here
// Then exit the loop for grading
break;
}
}
}
Based on your output for $scores, that array is just a single value, no associative array, so the loop should be:
// Iterate scores first (I don't know if you need the index or not)
foreach($scores as $scoreIndex => $score) {
// Search grading for this score (Index not needed here, just values)
foreach($data as $grading) {
// $score is an integer, not an array
if($score >= $grading['grade_min'] && $score <= $grading['grade_max']) {
// Score is inside this grading
// Echo here what you need
// Then exit the loop for grading
break;
}
}
}

PHP Nested Array is misaligned

I have a PHP loop that is pushing data into an array that will eventually be used to create a list of select options in my dropdown.
I feel like it is kinda close but I am doing something wrong somewhere.
The array of types needs to be part of the category it is associated with.
// Get the list of behavior types
public function _behavior_types()
{
$cat = $this->global_model->get_behavior_categories();
$typ = $this->global_model->get_behavior_types();
$output = array();
// Loop over our categories
foreach($cat as $c)
{
// Push the category name to an array
$output[] = $c['categoryName'];
// Loop over our types
foreach($typ as $t)
{
// If this type belongs to the category we are currently in, add it to the array
if($t['categoryID'] == $c['categoryID'])
{
array_push($output, $t);
}
}
}
return $output;
}
I have something out of place however and its causing the array to not be set up in the correct way.
Here is the current output:
Array
(
[0] => Negative
[1] => Array
(
[categoryID] => 2
[points] => -3
[typeID] => 4
[typeName] => Bad School Day
)
[2] => Positive
[3] => Array
(
[categoryID] => 1
[points] => 2
[typeID] => 1
[typeName] => Ate Dinner
)
[4] => Array
(
[categoryID] => 1
[points] => 2
[typeID] => 3
[typeName] => Brushed Teeth
)
[5] => Array
(
[categoryID] => 1
[points] => 3
[typeID] => 2
[typeName] => Completed Homework
)
)
Here is my desired output:
Array
(
[0] => Negative
[0] => Array
(
[categoryID] => 2
[points] => -3
[typeID] => 4
[typeName] => Bad School Day
)
[1] => Positive
[0] => Array
(
[categoryID] => 1
[points] => 2
[typeID] => 1
[typeName] => Ate Dinner
)
[1] => Array
(
[categoryID] => 1
[points] => 2
[typeID] => 3
[typeName] => Brushed Teeth
)
[2] => Array
(
[categoryID] => 1
[points] => 3
[typeID] => 2
[typeName] => Completed Homework
)
)
The dropdown in turn will look like:
Negative
Bad day at school
Positive
Ate Dinner
Brushed Teeth
Completed Homework
Your desired output is not really a valid array structure, at least how you have it typed. $output[0] cannot be both a string Negative and an array of options. I suggest making the category the key something like this:
// Get the list of behavior types
public function _behavior_types()
{
$cat = $this->global_model->get_behavior_categories();
$typ = $this->global_model->get_behavior_types();
$output = array();
// Loop over our categories
foreach($cat as $c)
{
// Push the category name to an array
$output[$c['categoryName']] = array();
// Loop over our types
foreach($typ as $t)
{
// If this type belongs to the category we are currently in, add it to the array
if($t['categoryID'] == $c['categoryID'])
{
array_push($output[$c['categoryName']], $t);
}
}
}
return $output;
}

Count multidimensional array keys with specific value

I've got an array and I need count the keys with a specific value, which is proving to be a nightmare.
Array([0] => Array
(
[0] => 1
[ruleid] => 1
[1] => Test Outbound Life 1
[rule_name] => Test Outbound Life 1
[2] => Life Insurance
[product_type] => Life Insurance
[3] => 1
[status] => 1
[4] => 1000
[priority] => 1000
[5] => 100
[quantity] => 100
[6] => 1-2-3-4-5-6-7-
[dayofweek] => 1-2-3-4-5-6-7-
[7] => 2
[income] => 2
[8] => external/arc.php
[integrationfile] => external/arc.php
[9] => 1
[partnerid] => 1
)
[1] => Array
(
[0] => 2
[ruleid] => 2
[1] => Test Outbound Life 2
[rule_name] => Test Outbound Life 2
[2] => Life Insurance
[product_type] => Life Insurance
[3] => 1
[status] => 1
[4] => 800
[priority] => 800
[5] => 100
[quantity] => 100
[6] => 1-2-3-4-5-6-7-
[dayofweek] => 1-2-3-4-5-6-7-
[7] => 2
[income] => 2
[8] => test.php
[integrationfile] => test.php
[9] => 1
[partnerid] => 1
) )
The array will be generated dynamically so the same array will appear in the array.
I want to count how many times the same ruleid appears is it will look like this:
Array{
[1] => 1
[2] => 1
}
Update: I need to count how many times ruleid = 2 or how many times ruleid = 1
So you want to count the number of time each ruleid appears inside an array.
Let's call this array $count. This is how I'd do it.
$count = array();
foreach($arrays as $array) { // $arrays is your big ass array containing arrays
// increment the value with the key corresponding to ruleid (improved by JustOnUnderMillions)
$count[$array['ruleid']] = isset($count[$array['ruleid']]) ? ($count[$array['ruleid']] + 1) : 1;
}
print_r(count); // should give you what you're looking for
I have worked it out by looping and counting how many times a ruleid appears in an array.
foreach ($count as $key => $value) {
$c = 0;
//check that outbound has passed all rules
foreach ($out as $k => $v) {
if ($v['ruleid']==$key) {
$c +=1;
}
}
if ($c==$value) {
//add valid outbound to array
foreach ($out as $k => $v) {
if ($v['ruleid']==$key) {
$valid[$key] = $v;
}
}
}
}
The loop checks the ruleid has passed all rules I had already counted in the $count variable.

complex multidimentional associative array process with foreach

I've had to ask this one again, sorry, but I'm having a problem trying to process this array. I have tried several different ways but none where right, here's the array:
Array (
[search] => Array (
[response] => Array (
[errors] =>
[number_of_hotels] => 1 of 1
)
[lr_rates] => Array (
[hotel] => Array (
[hotel_ref] => 3116
[hotel_currency] => [U] => USD
[hotel_rooms] => Array (
[room] => Array (
[ref] => 6382
[type] => 1
[type_description] => Standard
[sleeps] => 8
[rooms_available] =>
[adults] => 8
[children] =>
[breakfast] => false
[dinner] => false
[description] =>
[alternate_description] =>
[rack_rate] => 82.01
[date] => 19/08/201220/08/201221/08/2012
[numeric_hotelcurrencyprice] => FullFullFull
[formatted_date] => 19 August 201220 August 201221 August 2012
[price] => FullFullFull
[hotelcurrencyprice] => FullFullFull
[numeric_price] => FullFullFull
[requested_currency] => GBPGBPGBP
[numeric_hotelcurrencyprice] => FullFullFull
[available_online] => false
[minimum_nights] => 1
[bed_type] =>
[cancellation_policy] =>
[cancellation_days] =>
[cancellation_hours] =>
[room_terms] =>
)
[room] => Array (
[ref] => 6382
[type] => 1
[type_description] => Standard
[sleeps] => 8
[rooms_available] =>
[adults] => 8
[children] =>
[breakfast] => false
[dinner] => false
[description] =>
[alternate_description] =>
[rack_rate] => 82.01
[date] => 19/08/201220/08/201221/08/2012
[numeric_hotelcurrencyprice] => FullFullFull
[formatted_date] => 19 August 201220 August 201221 August 2012
[price] => FullFullFull
[hotelcurrencyprice] => FullFullFull
[numeric_price] => FullFullFull
[requested_currency] => GBPGBPGBP
[numeric_hotelcurrencyprice] => FullFullFull
[available_online] => false
[minimum_nights] => 1
[bed_type] =>
[cancellation_policy] =>
[cancellation_days] =>
[cancellation_hours] =>
[room_terms] =>
)
)
[cancellation_type] => First Night Stay Chargeable
[cancellation_policy] => 2 Days Prior to Arrival
[CityTax] => Array (
[TypeName] =>
[Value] =>
[OptedIn] =>
[IsCityTaxArea] =>
)
)
)
)
)
Ok, I need to traverse the array and create a loop, so for every instance of ROOM it will repeat the process. Then i need to extract the data from room array and use it to populate rows in MySQL for each instance of room.
This is the code I have so far which prints the names and values in the room array. However, it only gets one of the room arrays. What can I do to read all of the rooms? I am also thinking this is too many for-each but don't seem to be able to traverse down ['']['']['']...
or by just using the associative name.
foreach($arr['search'] as $lr_rates) {
foreach($lr_rates['hotel'] as $hotel) {
foreach($hotel['room'] as $field => $value){
print $field;print $value;
}
}
}
It might also be worth mentioning the values in these arrays are always fluctuating.
I think you can really simplify this quote a bit. If you know that this will always be the structure then you can jump right down into the hotels and then into the rooms.
foreach($arr['search']['lr_rates']['hotel'] as $hotel) {
// You can access all of the keys in the hotel array here
foreach($hotel['hotel_rooms'] as $room) {
// Do stuff with the room array
}
}
I would recommend either building your insert script on the fly and calling the database just once for the write, or if you are updating then using a transaction. As the number of rooms gets larger you will slow your script down with a bunch of writes to disk.
the formatting of your data's output is very bad and unreadable. I cannot really identify what you are trying to do.
possibility: the inner array [hotel_rooms] => Array () uses the key room multiple times. as array keys are unique, you overwrite the data at the index room. this is why you only get one room.
possibility: there are rooms inside a room -> use a recursive function to iterate over all rooms like this:
function handleRoom(array $room) {
// do something with $room
if (array_key_exists('room', $room)) {
handleRoom($room['room']);
}
}
$room = array(
'some' => 'room',
'data' => 'and another',
'room' => array(
'is' => 'inside',
'of the' => 'main room',
),
);
handleRoom($room);

Multidimensional Array Pushing/Adding?

I want to create something like the following array
[Schedule_Date_Group] => Array
(
[Schedule_Date] => Array
(
[Friday, September 16, 2011] => Array
(
[Schedule_Item] => Array
(
[nid] => 763
[time] => 1:15 PM
[title] => What a Publisher Does: 5 Reasons Why You Need a...
[event_type] => events
[length] =>
[movie_type] =>
[details] =>
)
[Schedule_Item] => Array
(
[nid] => 763
[time] => 1:15 PM
[title] => What a Publisher Does: 5 Reasons Why You Need a...
[event_type] => events
[length] =>
[movie_type] =>
[details] =>
)
)
)
)
But I have a few issues, first the array seems to be getting created with a preceding # for the first value. Example
[7] => Array
(
[Schedule_Date_Group] => Array
(
And my arrays are not pushing it under the Date Array ([Friday, September 16, 2011] => Array) They are just being added to the end as a normal array. Example
[7] => Array
(
[Schedule_Date_Group] => Array
(
[Schedule_Date] => Array
(
[Friday, September 16, 2011] => Array
(
[Schedule_Item] => Array
(
[nid] => 763
[time] => 1:15 PM
[title] => What a Publisher Does: 5 Reasons Why You Need a...
[event_type] => events
[length] =>
[movie_type] =>
[details] =>
)
)
)
)
)
[8] => Array
(
[Schedule_Item] => Array
(
[nid] => 764
[time] => 1:30 PM
[title] => Navigating the Road to Licensing Music For Your...
[event_type] => events
[length] =>
[movie_type] =>
[details] =>
)
)
How can I fix these two issues. They are again, #'s preceding the Schedule_Date_Group array and the sub arrays being added to the end rather then nested under the date group array.
PHP For the main schedule item and date group part
$xml[] = array("Schedule_Date_Group" => array("Schedule_Date" => array($pretty_date => array("Schedule_Item" => array("nid" => $do['nid'], "time" => $pretty_time, "title" => $title, "event_type" => $do['field_event_type_value'], "length" => $do['field_length_value'], "movie_type" => $do['field_movie_type_value'], "details" => $schedule_details)))));
PHP for the sub menu items
$xml[] = array("Schedule_Item" => array("nid" => $do['nid'], "time" => $pretty_time, "title" => $title, "event_type" => $do['field_event_type_value'], "length" => $do['field_length_value'], "movie_type" => $do['field_movie_type_value'], "details" => $schedule_details));
It is being looped through so there is no way for me to just create a giant array. And if a new "Schedule Date" is set it will create a new [Schedule_Date_Group] => Array
(
[Schedule_Date] => Array
(
[Friday, September 16, 2011] => Array
(
and all the sub content should go under that new one.
So I would end up with
DATE
- Schedule_Item 1
- Schedule_Item 2
- Schedule_Item 3
- Schedule_Item 4
New Date
- Schedule Item 5
- Schedule Item 6
etc...
Any help?
Firstly, using a huge array to manually generate some XML like this is not the way to do it. Use something like XMLWriter or DOM instead, then you can build your document on the fly as you obtain your data. However, if you really want to, or are forced to do it like this, read on...
Secondly, what you are trying to do cannot be done. This is because you want use the same array key for multiple entries which won't work - you will just end up overwriting your previous entry.
Thirdly, your numeric keys are appearing because you are using $xml[] (array_push() behaves in the same way) and it will always add a numeric key because you have not told it what you want your text key to be.
Fourthly, your extra items are being added to the outer level of the array because that is what you have told PHP to do. $xml[] will always add a new key to the outer level of the $xml variable because you have not told PHP you are dealing with an inner array.
Your structure needs to be more like this:
$scheduleDateGroup = array (
'Friday, September 16, 2011' => array (
// These are your schedule items...
0 => array( ... ),
1 => array( ... ),
2 => array( ... ),
...
),
'Saturday, September 17, 2011' => array (
0 => array( ... ),
1 => array( ... ),
2 => array( ... ),
...
),
...
);
...and you can push new items onto specific days like this:
$scheduleDateGroup[$date][] = array( ... );
Then you can loop through it and turn it into XML with something like this:
echo "<Schedule_Date_Group>\n";
foreach ($scheduleDateGroup as $day => $schedules) {
echo " <Schedule_Date date=\"$day\">\n";
foreach ($schedules as $item) {
echo " <Schedule_Item";
foreach ($item as $attr => $value) echo " $attr=\"$value\"";
echo " />\n";
}
echo " </Schedule_Date>\n";
}
echo "</Schedule_Date_Group>";

Categories