Associative array inside array in PHP - php

After fetching a result from the database, and preparing the array for the JSON enconde, I face a dilemma on how to reference the array 'data' inside the main array.
The "[0]" by far is an error of my logic...
while ($row =$result->fetch()) {
$name = $row['country'];
$id = $row['id']
$username = $row['username'];
$subtotal = $row['subtotal'];
if ( /* If $id exist in array row['series']}*/ ) {
///?????/////
/// Add array to 'DATA'
////?????////
$rows['series']["$id"]["$name"]['data'][]=array("$username", $subtotal);
}
else {
$rows['series'][]= array('id' => "$id", 'name' => "$name", 'data' => array("$username", $subtotal));
}
The vardump show as follow:
array(1) {
["series"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(7) "hn"
["name"]=>
string(8) "HN"
["data"]=>
array(2) {
[0]=>
string(17) "GK_5"
[1]=>
string(5) "86040"
}
}
[1]=>
array(3) {
["id"]=>
string(7) "hn"
["name"]=>
string(8) "HN"
["data"]=>
array(2) {
[0]=>
string(17) "GK_8"
[1]=>
string(5) "20358"
}
}
}
}
But I want to add the last item with same id/name like this:
array(1) {
["series"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(7) "hn"
["name"]=>
string(8) "HN"
["data"]=>
array(2) {
[0]=>
string(17) "GK_5"
[1]=>
string(5) "86040"
}
array(2) {
[0]=>
string(17) "GK_8"
[1]=>
string(5) "20358"
}
}
}
}

The most natural way would be to change your data structure a bit, so that the series array is indexed by the row ID instead of an arbitrary running index. The would allow you to rewrite your loop to (using mysqli syntax as an example):
$stmt->bind_result($id, $country, $username, $subtotal);
$series = array();
while ( $stmt->fetch() ) {
$series[$id]['country'] = $country;
$series[$id]['data'][] = array(
'username' => $username,
'subtotal' => $subtotal,
);
}
which will give you a data structure like:
$series = array(
'hn' => array(
'country' => 'HN',
'data' => array(
0 => array(
'username' => 'GK_5',
'subtotal' => 86040
),
1 => array(
'username' => 'GK_8',
'subtotal' => 20358
),
// ...
)
),
// ...
);
If you need the data in the exact format shown in your post, you can of course loop over this array with foreach to transform it, e.g.:
$rows = array();
foreach ( $series as $id => $record ) {
$record['id'] = $id;
$rows['series'][] = $record;
}

Related

Merge two different array data in one array php

I want to merge two different array data in one array, but i'm confuse how to use array_push in this case.
this is example of my data input:
["author"]=>
array(2) {
[0]=>
string(1) "John"
[1]=>
string(1) "Doe"
}
["title"]=>
array(2) {
[0]=>
string(1) "book a"
[1]=>
string(1) "book b"
}
And the result in one array that i mean, like this:
["books"]=>
array(2) {
[0] =>
array(2) {
["author"]=>
string(1) "John"
["title"]=>
string(1) "book a"
}
[1] =>
array(2) {
["author"]=>
string(1) "Doe"
["title"]=>
string(1) "book b"
}
}
I already try using this way but it just return 1 from each array:
$data['books'] = [];
array_push($data['books'], [
'author' => $data['author'],
'title' => $data['title']
]);
if (isset($data['books'])) {
foreach ($data['books'] as $k => $v) {
$data['books'][$k]['author'] = (int)$v['author'];
$data['books'][$k]['title'] = (int)$v['title'];
}
}
result:
["books"]=>
array(1) {
[0]=>
array(2) {
["author"]=>
int(1)
["title"]=>
int(1)
}
}
You have to transpose your arrays with the keys in mind.
function transpose(array $arr){
$transArr = [];
foreach($arr as $keyRow => $subArr) {
foreach($subArr as $keyCol => $value) {
$transArr[$keyCol][$keyRow] = $value;
}
}
return $transArr;
}
This function can be used universally for similar problems. The function comes from this class.
How to use:
$input = [
"author"=> ["John","Doe"],
"title" => ["book a","book b"],
];
$books = transpose($input);
echo '<pre>';
var_export($books);
Or if you want to use the class:
$books = tableArray::create($input)
->transpose()
->fetchAll()
;
Output:
array (
0 =>
array (
'author' => 'John',
'title' => 'book a',
),
1 =>
array (
'author' => 'Doe',
'title' => 'book b',
),
)
If "author" and "title" exist as two arrays, $ input must first be created like this:
$input = ['author' => $arrayAuthor, 'title' => $arrayTitle];

Grouping array items based on string value

I am trying to group an array by sport. It could be n number of sports. Finally, then create a new array with it. Is there an efficient way to this without going overkill?
$sports = [
['sport' => 'soccer', 'id' => 97487];
['sport' => 'soccer', 'id' => 244800];
['sport' => 'soccer', 'id' => 258740];
['sport' => 'basketball', 'id' => 147884];
['sport' => 'baseball', 'id' => 222240];
['sport' => 'baseball', 'id' => 222245];
];
Initial array:
array(6) {
[0]=>
array(2) {
["sport"]=>
string(6) "soccer"
["id"]=>
int(97487)
}
[1]=>
array(2) {
["sport"]=>
string(6) "soccer"
["id"]=>
int(244800)
}
[2]=>
array(2) {
["sport"]=>
string(6) "soccer"
["id"]=>
int(258740)
}
[3]=>
array(2) {
["sport"]=>
string(10) "basketball"
["id"]=>
int(147884)
}
[4]=>
array(2) {
["sport"]=>
string(8) "baseball"
["id"]=>
int(222240)
}
[5]=>
array(2) {
["sport"]=>
string(8) "baseball"
["id"]=>
int(222245)
}
}
Desired results:
array(3)
{
[0]=>
array(3) {
[0]=>
array(2) {
["sport"]=>
string(6) "soccer"
["id"]=>
int(97487)
}
[1]=>
array(2) {
["sport"]=>
string(6) "soccer"
["id"]=>
int(244800)
}
[2]=>
array(2) {
["sport"]=>
string(6) "soccer"
["id"]=>
int(258740)
}
}
[1]=>
array(1) {
[0]=>
array(2) {
["sport"]=>
string(10) "basketball"
["id"]=>
int(147884)
}
}
[2]=>
array(2) {
[0]=>
array(2) {
["sport"]=>
string(8) "baseball"
["id"]=>
int(222240)
}
[1]=>
array(2) {
["sport"]=>
string(8) "baseball"
["id"]=>
int(222245)
}
}
}
You can group the array like so:
$sports = [
['sport' => 'soccer', 'id' => 97487],
['sport' => 'soccer', 'id' => 244800],
['sport' => 'soccer', 'id' => 258740],
['sport' => 'basketball', 'id' => 147884],
['sport' => 'baseball', 'id' => 222240],
['sport' => 'baseball', 'id' => 222245]
];
// we will build an array here where the key is the sport
// name and the value is an array of objects pertaining
// to that sport i.e. 'basketball' => [bb1, bb2, ...]
$array = array();
// now consider every sport object in your original array
foreach($sports as $key => $item)
{
if (array_key_exists($item['sport'], $array)) {
// we encountered this same sport in the past so we
// know $array['sportName'] already exists and can
// push right to it
$array[$item['sport']][] = $item;
} else {
// we have never seen this sport before and now must
// insert the sport into $array['sportName'] = []
// and push this sport object to it
$array[$item['sport']] = [$item];
}
}
// since $array's keys are the names of the sports themselves, but
// you want the keys to be numeric, this will build a new array
// from just the values of $array which at this point contains
// grouped arrays of sport objects
$result = array_values($array);
// print the results for good measure :)
print_r($result);
This works by looping over your sports array and building a second array of [sportName => arrayOfThatSport]. Inside the for loop, we are checking to see if a given sport already exists in this array. If it does, great, add the sport to the corresponding array for that sport. Otherwise, create a new array for that sport available at $array['sportName'] = [sportObject]. If you consider several iterations of the loop you will see that we're either always adding to an existing $array['sportName'] array, or creating a new array at this position whenever we encounter a new sport we've never seen before. This gives us a final array similar to: [ "sport
: [...], "sport2": [...] ] but in your case you want a numeric array not an associative array, hence the call to array_values.
This is my suggested solution.
$groupedSports = [];
foreach ($sports as $item) {
if (empty($groupedSports[$item['sport']])) {
$groupedSports[$item['sport']] = [];
}
$groupedSports[$item['sport']][] = $item;
}
Short explanation:
line 1: we initialize an empty array
line 2: we start a loop on the original array
line 3-5: if it's the first occurrence for the current sport, we initialize an empty array for that sport (avoid warnings)
line 6: we assign current item to the appropriate array

multiple arrays in codeigniter session

I'm trying to get multiple arrays in a CodeIgniter session:
if ($this->session->has_userdata('products')){
$outerarray = array(
$array = array(
'id' => $id,
'quantity' => 1
));
array_push($outerarray, $this->session->userdata('products'));
$data['products'] = $outerarray;
$this->session->set_userdata($data);
} else {
$data['products'] = array(
'id' => $id,
'quantity' => 1
);
$this->session->set_userdata($data);
}
The else part works fine, but when there is already an array in the session it will put it like this in the session:
array(2) { [0]=> array(2) { ["id"]=> string(1) "7" ["quantity"]=> int(1) } [1]=> array(2) { ["id"]=> string(1) "1" ["quantity"]=> int(1) } }
what i really want to see is this:
array(2) { ["id"]=> string(1) "7" ["quantity"]=> int(1) } array(2) { ["id"]=> string(1) "1" ["quantity"]=> int(1) }
Is there a possibility to have only the content of the $outerarray in the session and not the whole $outerarray itself?
You have to do it this way:
$data = array('id' => 1, 'quantity' => 2);
if (isset($_SESSION['products'])) {
array_push($_SESSION['products'], $data);
}
else {
$_SESSION['products'] = array($data);
}

PHP Extract value from nested array and place in a loop to echo value

I'm trying to extract the virtual machine names that are being pulled from a vcenter server via the below SOAP requests. Whilst I'm getting the results (see the var_dump below), I can't figure out how to put a loop in to get the names as there are many embedded arrays and everything I try either returns an error or Array. I appreciate this is probably quite a simple one but i just can't figure it out.
It's the name value in the code extract below i'm trying to get.
$request->specSet = array (
'propSet' => array (
array ('type' => 'VirtualMachine', 'all' => 0, 'pathSet' => array('name','runtime.powerState', 'config.hardware.numCPU', 'config.hardware.memoryMB')),
),
PHP Page
$ss1 = new soapvar(array ('name' => 'FolderTraversalSpec'), SOAP_ENC_OBJECT, null, null, 'selectSet', null);
$ss2 = new soapvar(array ('name' => 'DataCenterVMTraversalSpec'), SOAP_ENC_OBJECT, null, null, 'selectSet', null);
$a = array ('name' => 'FolderTraversalSpec', 'type' => 'Folder', 'path' => 'childEntity', 'skip' => false, $ss1, $ss2);
$ss = new soapvar(array ('name' => 'FolderTraversalSpec'), SOAP_ENC_OBJECT, null, null, 'selectSet', null);
$b = array ('name' => 'DataCenterVMTraversalSpec', 'type' => 'Datacenter', 'path' => 'vmFolder', 'skip' => false, $ss);
$res = null;
try
{
$request = new stdClass();
$request->_this = $ret->propertyCollector;
$request->specSet = array (
'propSet' => array (
array ('type' => 'VirtualMachine', 'all' => 0, 'pathSet' => array('name','runtime.powerState', 'config.hardware.numCPU', 'config.hardware.memoryMB')),
),
'objectSet' => array (
'obj' => $ret->rootFolder,
'skip' => false,
'selectSet' => array (
new soapvar($a, SOAP_ENC_OBJECT, 'TraversalSpec'),
new soapvar($b, SOAP_ENC_OBJECT, 'TraversalSpec'),
),
)
);
$res = $client->__soapCall('RetrieveProperties', array((array)$request));
}
catch (Exception $e)
{
echo $e->getMessage();
}
Var_dump()
object(stdClass)#46 (1) {
["returnval"]=>
array(2) {
[0]=>
object(stdClass)#47 (2) {
["obj"]=>
object(stdClass)#48 (2) {
["_"]=>
string(5) "vm-35"
["type"]=>
string(14) "VirtualMachine"
}
["propSet"]=>
array(4) {
[0]=>
object(stdClass)#49 (2) {
["name"]=>
string(24) "config.hardware.memoryMB"
["val"]=>
int(128)
}
[1]=>
object(stdClass)#50 (2) {
["name"]=>
string(22) "config.hardware.numCPU"
["val"]=>
int(1)
}
[2]=>
object(stdClass)#51 (2) {
["name"]=>
string(4) "name"
["val"]=>
string(7) "test123"
}
[3]=>
object(stdClass)#52 (2) {
["name"]=>
string(18) "runtime.powerState"
["val"]=>
string(10) "poweredOff"
}
}
}
[1]=>
object(stdClass)#53 (2) {
["obj"]=>
object(stdClass)#54 (2) {
["_"]=>
string(5) "vm-36"
["type"]=>
string(14) "VirtualMachine"
}
["propSet"]=>
array(4) {
[0]=>
object(stdClass)#55 (2) {
["name"]=>
string(24) "config.hardware.memoryMB"
["val"]=>
int(128)
}
[1]=>
object(stdClass)#56 (2) {
["name"]=>
string(22) "config.hardware.numCPU"
["val"]=>
int(1)
}
[2]=>
object(stdClass)#57 (2) {
["name"]=>
string(4) "name"
["val"]=>
string(7) "test456"
}
[3]=>
object(stdClass)#58 (2) {
["name"]=>
string(18) "runtime.powerState"
["val"]=>
string(10) "poweredOff"
}
}
}
}
}
I knew it was a relatively simple fix. I added the below to the code to get the required values out.
$tvCPU = 0;
$tvRAM = 0;
echo "<table><tr><td width='450px'>Name</td><td width='100px'>vRAM (MB)</td><td width='100px'>vCPU</td><td width='100px'>Power State</td></tr>";
$arrlength=count($res ->returnval);
for($x=0;$x<$arrlength;$x++) {
$name = $res -> returnval[$x] -> propSet[2]->val;
$vRam = $res -> returnval[$x] -> propSet[0]->val;
$vCPU = $res -> returnval[$x] -> propSet[1]->val;
$pState = $res -> returnval[$x] -> propSet[3]->val;
echo "<tr><td width='450px'>".$name."</td><td>".$vRam."</td><td>".$vCPU."</td><td>".$pState."</td> </tr>";
$tvCPU = $tvCPU + $vCPU;
$tvRAM = $tvRAM + $vRam;
}
echo "<tr><td width='450px'>Total VMs - ".$x."</td> <td>". $tvRAM."</td> <td>". $tvCPU."</td> </tr>";

Remove duplicates from multidimensional associative array in php if two values match

I have a multidimensional array of the following structure and I want to remove duplicates from it. For example if the ["amount"] is the same for two ["cities"] but the ["time"] is the same or different then I count this is a duplicate and want to remove this node from the array.
In the following example I want to remove completely node 0 from the array as the city and amount are the same as node 1. They are both Bristol (Bristol, United Kingdom) and 373 Even though the time is different being 17:15 and 17:16.
If the times are different as in this case then I would remove the later time.
array(8) {
[0]=>
array(3) {
["time"]=>
string(5) "17:16"
["city"]=>
string(33) "Bristol (Bristol, United Kingdom)"
["amount"]=>
int(373)
}
[1]=>
array(3) {
["time"]=>
string(5) "17:15"
["city"]=>
string(33) "Bristol (Bristol, United Kingdom)"
["amount"]=>
int(373)
}
[2]=>
array(3) {
["time"]=>
string(5) "17:16"
["city"]=>
string(37) "Wednesbury (Sandwell, United Kingdom)"
["amount"]=>
int(699)
}
[3]=>
array(3) {
["time"]=>
string(5) "17:16"
["city"]=>
string(45) "Wolverhampton (Wolverhampton, United Kingdom)"
["amount"]=>
int(412)
}
[4]=>
array(3) {
["time"]=>
string(5) "17:15"
["city"]=>
string(33) "Swansea (Swansea, United Kingdom)"
["amount"]=>
int(249)
}
[5]=>
array(3) {
["time"]=>
string(5) "17:16"
["city"]=>
string(39) "Watford (Hertfordshire, United Kingdom)"
["amount"]=>
int(229)
}
[6]=>
array(3) {
["time"]=>
string(5) "17:14"
["city"]=>
string(39) "Nottingham (Nottingham, United Kingdom)"
["amount"]=>
int(139)
}
[7]=>
array(3) {
["time"]=>
string(5) "17:13"
["city"]=>
string(31) "Dartford (Kent, United Kingdom)"
["amount"]=>
int(103)
}
}
Try this:
$result = array();
foreach ($array as $place) {
if (!array_key_exists($place['time'], $result)) {
$result[$place['time']] = $place;
}
}
<?php
$data = array(
array(
'time' => '17:16',
'city' => 'Bristol',
'amount' => 373,
),
array(
'time' => '18:16',
'city' => 'Bristol',
'amount' => 373,
),
array(
'time' => '18:16',
'city' => 'Wednesbury',
'amount' => 699,
),
array(
'time' => '19:16',
'city' => 'Wednesbury',
'amount' => 699,
),
);
$tmp = array();
foreach ($data as $row) {
$city = $row['city'];
$amount = $row['amount'];
if (!isset($tmp[$city][$amount])
|| $tmp[$city][$amount]['time'] < $row['time']) {
$tmp[$city][$amount] = $row;
}
}
$data = array();
foreach ($tmp as $cities) {
foreach ($cities as $city) {
$data[] = $city;
}
}
var_dump($data);
Create a 2-dimensional associative array, where one dimension is keyed off the city, and the other is the amount:
$assoc = array();
foreach ($data as $el) {
$city = $el['city'];
$amount = $el['amount'];
if (isset($assoc[$city]) {
$assoc[$city][$amount] = $el;
} else {
$assoc[$city] = array($amount => $el);
}
}
// Now gather up all the elements back into a single array
$result = array();
foreach ($assoc as $cities)
foreach ($cities as $city) {
$result[] = $city;
}
}

Categories