How to group these arrays accordingly? - php

I'm using PDO to run a mysql query with 2 joins and this is the result I get from the database:
Array
(
[0] => Array
(
[id] => 489
[cluster_id] =>
[label_value_id] => 4
[label_id] => 1
[int_value] => 40
)
[1] => Array
(
[id] => 489
[cluster_id] =>
[label_value_id] => 6
[label_id] => 2
[int_value] => 20
)
[2] => Array
(
[id] => 489
[cluster_id] =>
[label_value_id] => 9
[label_id] => 3
[int_value] => 10
)
)
The idea is that there will be multiple id's later on but for simplicities sake I only have 1 entry with id 489 for now.
I need the 3 arrays (cause of the joins) to be 1 array that looks something like this, I want a subarray based on the label-value_id => int_value relationship:
Array
(
[0] => Array
(
[id] => 489
[cluster_id] =>
[label_value_id] => 4
[label_id] => 1
[int_value] => 40
[vector_data] => Array
(
[4] => 40
[6] => 20
[9] => 10
)
)
)
I'd rather have this done in the PHP and not the Query because I dont have control over the queries when I implement this into the live application.
Any help is much appreciated!

You can use another container for gathering all batches which share the same id using its keys to transfer them. On initialization, create another container for that vector, then just push them line any normal array value:
$result = array();
foreach($array as $values) {
// initialization
if(!isset($result[$values['id']])) {
$result[$values['id']] = $values;
}
$result[$values['id']]['vector_data'][$values['label_value_id']] = $values['int_value'];
}
// $result = array_values($result); // optional key reindex
Sample Output

You can process your array from DB like this:
$pdo = array(
array(
"id" => 489,
"label_value_id" => 4,
"int_value" => 40,
),
array(
"id" => 489,
"label_value_id" => 6,
"int_value" => 20,
),
array(
"id" => 489,
"label_value_id" => 9,
"int_value" => 10,
),
);
$result = array();
foreach ($pdo as $array) {
if (!isset($result[$array['id']])) {
$result[$array['id']] = array(
"id" => $array['id'],
"vector_data" => array()
);
}
$result[$array['id']]['vector_data'][$array['label_value_id']] = $array['int_value'];
}

I have the same situation, and i solve it through PDO.
Here available examples. I reach same result with code:
$sth->fetchAll(PDO::FETCH_ASSOC|PDO::FETCH_GROUP);
think you should try it...

Related

PHP - Add a new element into each multidimensional array

I have an array that looks like this:
Array
(
[0] => stdClass Object
(
[quiz_id] => 1033
[quiz_venue] => 6
[quiz_host] => 46
[quiz_golden_question] => 100
[quiz_golden_question_outcome] => 0
[quiz_running] => 1
[quiz_status] => 100
[quiz_trainee] => 0
)
[1] => stdClass Object
(
[quiz_id] => 985
[quiz_venue] => 57
[quiz_host] => 21
[quiz_golden_question] => 0
[quiz_golden_question_outcome] => 0
[quiz_running] => 1
[quiz_status] => 310
[quiz_trainee] => 0
)
I want to go through each array, and insert a new value (quiz_venue_name), this is what I have;
$quizzes = $wpdb->get_results( $prepared );
foreach ($quizzes as $quiz => $item) {
$venuetitle = get_the_title($item->quiz_venue);
$quizzes['quiz_venue_name'] = $venuetitle;
}
return $quizzes;
However, all it does is add the new values to the very end of the multidimensional array as new arrays - rather than adding them into each!
I feel like I'm doing something obvious wrong, so any help is much appreciated!
The end result I need would be;
Array
(
[0] => stdClass Object
(
[quiz_id] => 1033
[quiz_venue] => 6
[quiz_host] => 46
[quiz_golden_question] => 100
[quiz_golden_question_outcome] => 0
[quiz_running] => 1
[quiz_status] => 100
[quiz_trainee] => 0
[quiz_venue_name] => NEW VALUE
)
[1] => stdClass Object
(
[quiz_id] => 985
[quiz_venue] => 57
[quiz_host] => 21
[quiz_golden_question] => 0
[quiz_golden_question_outcome] => 0
[quiz_running] => 1
[quiz_status] => 310
[quiz_trainee] => 0
[quiz_venue_name] => NEW VALUE
)
Your $quizzes variable is an array of objects (Instance of stdClass), so you should use it attribute to set value in each iteration ($item->quiz_venue_name instead of $quizzes['quiz_venue_name']):
...
foreach ($quizzes as $quiz => $item) {
$venuetitle = get_the_title($item->quiz_venue);
$item->quiz_venue_name = $venuetitle;
}
...
In fact the $quizzes['quiz_venue_name']=... code will be set a value for index quiz_venue_name in root of $quizzes array.

how to remove array value from array when value not same from both the value [duplicate]

This question already has answers here:
How to Remove value from an array using another array with multiple values?
(4 answers)
Closed 4 years ago.
I have two array, and i want to remove duplicate record from array2. i don't want to link_id 35 record in array 2 because link_id 35 record is present in array1 so it's not show in array2.
I tried with array_map and Unique methods but it's not working well because i think both the array doesn't have the same value.
$array1=
[0] => stdClass Object
(
[link_id] => 35
[link_name] => Test Listerine cool mint packets 3 pack
[alias] => aa
[link_desc] =>
[user_id] => 47
[link_hits] => 103
[link_votes] => 1
[link_rating] => 5.000000
[link_featured] => 0
[link_published] => 1
[link_approved] => 1
[link_template] =>
)
[1] => stdClass Object
(
[link_id] => 373
[link_name] => Test Subject Data Collection Fish Fresh Yellow Tail
[alias] => ba
[link_desc] =>
[user_id] => 47
[link_hits] => 198
[link_votes] => 8
[link_rating] => 2.875000
[link_featured] => 0
[link_published] => 1
[link_approved] => 1
[link_template] =>
)
$array2 =
[0] => stdClass Object
(
[link_id] => 35
[link_name] => Test Listerine cool mint packets 3 pack
[link_desc] =>
[lat] => 0.000000
[lng] => 0.000000
[contactperson] =>
[cat_name] => AA - Made in USA
[link_votes] => 1
[link_rating] => 5.000000
[link_featured] => 0
[value] => 30020864
)
[1] => stdClass Object
(
[link_id] => 541
[link_name] => Test Subject Data Collection Fish Fresh Yellow Tail
[link_desc] =>
[lat] => 25.182573
[lng] => -80.093079
[country] => United States
[postcode] => 33431
[contactperson] => Captain Jack Certified Charters
[cat_name] => BA - Product of USA
[link_votes] => 8
[link_rating] => 2.875000
[link_featured] => 0
[value] => NA
)
You can do that with array-filter. First extract all the ids from the first array and then filter the second array based of those ids.
$arr1 = array( (object) ["link_id"=> 35, "key" => "AAA"], (object) ["link_id"=> 373, "key" => "BBB"]);
$arr2 = array( (object) ["link_id"=> 35, "key" => "CCC"], (object) ["link_id"=> 341, "key" => "DDD"]);
$ids = array_column($arr1, "link_id");
$arr2 = array_filter($arr2, function ($e) use ($ids) {
return !in_array($e->link_id, $ids); //keep him in arr2 only if NOT in ids of arr1
});
Updated more fast answer Consider big amount of data (as for #mickmackusa comment) use this:
$ids = [];
foreach($arr1 as $e)
$ids[$e->link_id] = true;
$arr2 = array_filter($arr2, function ($e) use ($ids) {
return !isset($ids[$e->link_id]);
});
First solution is in O(n^2) and the second is in O(n)
This should do in php7.
Untested code:
var_export(array_diff_key(array_column($array2, null, 'link_id'), array_column($array1, null, 'link_id'));
Assign new 1st level keys to both arrays, then filter on those keys.
Checking against keys will be more efficient than making iterated calls of in_array.

Moving values from one array to another in 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.

Get keys of 5 bigests value from array

I have one problem. I must get 5 images which rates are the biggest. I have table which key = image_id and value = average rating.
Below is print_r of this array
Array ( ['5'] => 5.00 ['4'] => 3.05 ['12'] => 3.00 ['11'] => 4.00 ['21'] => 2.11 ['53'] => 4.44 )
For example
['5'] => 5.00
means that img which id = '5' have rating 5.00
Expected output 2 Arrays ($id and $rating)
Array ( [0] => '5' [1] => '53' [2] => '11' [3] => '4' [4] => '12' )
Array ( [0] => '5.00' [1] => '4.44' [2] => '4.00' [3] => '3.05' [4] => '3.00' )
Can you help me in this?
Use arsort(); and array_slice();
You can also avoid making 2 separate arrays with functions like array_keys(); and array_values();
// Original array
$array = array(
5 => 5.00,
4 => 3.05,
12 => 3.00,
11 => 4.00,
21 => 2.11,
53 => 4.44
);
// Sort array & maintain keys
arsort($array);
// Now get the first 5 elements, keeping the keys
$array = array_slice($array, 0, 5, true);
// IDs
print_r(array_keys($array));
// Ratings
print_r(array_values($array));
Have you tried to use arsort or uasort?

How to create a new key and store array values in a multidimensional way PHP

I have data here: First, the result of my first function named getsiteaccounts()
Array
(
[0] => Array
(
[SiteID] => 2
[AID] => 5
)
[1] => Array
(
[SiteID] => 2
[AID] => 3
)
[2] => Array
(
[SiteID] => 6
[AID] => 4
)
And the result of my second function named bindGHComponentsToSites()
Array
(
[2] => Array
(
[SiteID] => 2
[Balance] => 19000.00
[MinBalance] => 100000.00
[MaxBalance] => 1000000.00
[OwnerAID] => 5
[GroupID] => 1
[Deposit] => 1500
[Reload] => 1000
[Redemption] => 1000
)
)
Then, add the key of [CorpAID] pointing to the list of OwnerAID. BY the way, OwnerAID and AID are the same. As you can see SiteID => 2 owned by two OwnerAID => 5 and 3. Here's should be the result:
Array([0])=> Array (
[SiteID] => 2
[Balance] => 19000.00
[MinBalance] => 100000.00
[MaxBalance] => 1000000.00
[OwnerAID] => 5
[GroupID] => 1
[Deposit] => 1500
[Reload] => 1000
[Redemption] => 1000
[CorpAID] => Array(
[0] => 5
[1] => 3
)
)
)
The SiteID => 6 should not be print since it only owned by one AID. Is it possible to make it? Please guide me in proper way. Thank you in advance.
You can use a couple of foreach loops to do what you need:
<?php
$siteAccounts = array(
array('SiteID'=>2, 'AID'=>5),
array('SiteID' => 2, 'AID' => 3),
array('SiteID' => 6, 'AID' => 4)
);
$componentsToSites = array(array(
'SiteID' => 2,
'Balance' => 19000.00,
'MinBalance' => 100000.00,
'MaxBalance' => 1000000.00,
'OwnerAID' => 5,
'GroupID' => 1,
'Deposit' => 1500,
'Reload' => 1000,
'Redemption' => 1000
));
foreach ($componentsToSites as &$site) {
$aids = array();
foreach ($siteAccounts as $acct) {
if ($acct['SiteID'] === $site['SiteID'])
$aids[] = $acct['AID'];
}
$site['CorpAID'] = $aids;
}
print_r($componentsToSites);
Edit:
My original answer used array_walk rather than foreach, but due to compatibility issues I switched it. Here is the original code snippet for using array_walk:
array_walk($componentsToSites, function (&$site) use ($siteAccounts) {
$aids = array();
array_walk($siteAccounts, function ($acct) use ($site, &$aids) {
if ($acct['SiteID'] === $site['SiteID'])
$aids[] = $acct['AID'];
});
$site['CorpAID'] = $aids;
});

Categories