Php sorting multidimensional array? - php

How to sort the following array?
I have an multidimensional array that gets filled with total hours for each brand
$totalHours = array(
'brand' => array(),
'project' => array(),
'hours' => array()
);
The output is something like this (project is not filled):
array(3) {
["brand"]=>
array(3) {
[0]=>
string(4) "Nike"
[1]=>
string(9) "Coke Cola"
[2]=>
string(8) "Converse"
}
["project"]=>
array(3) {
[0]=>
string(6) "Bonobo"
[1]=>
string(4) "LDRU"
[2]=>
string(2) "US"
}
["hours"]=>
array(3) {
[0]=>
int(28)
[1]=>
int(106)
[2]=>
string(1) "2"
}
}
Now I would like to sort the array based on the "hours" field.
I've tried the array_multisort but it seems like I simply don't get how this function works and how to apply it to this array.
I have been able to sort an single array with just one row of values. If I apply that to this problem im sorting only the hours field, leaving the others unsorted and therefore the array is corrupted.
The "project" does actually contains a string. It always does. In this example I didn't filled it.

array_multisort should work:
$totalHours = array(
'brand' => array('Nike', 'Coke Cola', 'Converse'),
'project' => array(),
'hours' => array(28, 106, '2')
);
array_multisort($totalHours['hours'], $totalHours['brand']);
var_dump($totalHours);

That data format is not very convenient because there is no direct association between brands and hours, they even sit in different arrays! Plus, the last hour is a string, not an integer.
We're going to have to create an intermediate array to associate them and sort them. We'll then re-inject everything in the original array.
// Make sure both arrays of brands and hours and the same size
if (count($totalHours['brand']) != count($totalHours['hours'])) {
throw new Exception('Invalid data!');
}
// Make sure every hour record is an integer, not a string
$totalHours['hours'] = array_map('intval', $totalHours['hours']);
// array_combine will sort all arrays based on the sorting of the first one
array_multisort($totalHours['hours'], $totalHours['brand'], $totalHours['project']);
EDIT: Using array_multisort was #delprks 's idea originally. Here I applied it to both brand and project arrays.

You cant do that with a single array_* function!
if (project is not filled) always and the indexes of brand and hours are equal, then you can do:
$forsort = array_combine($totalHours["brands"],$totalHours["hours"]);
asort($forsort,SORT_NUMERIC);
$totalHours["brands"]=array_keys($forsort);
$totalHours["hours"]=array_values($forsort);
But, this is just an answer for you question, not best practise at all.

Related

Make multidimensional array with php and pdo

i want to edit a script i found online. is has an hardcoded array like this.
$servers = array(
'Google Web Search' => array(
'ip' => '',
'port' => 80,
'info' => 'Hosted by The Cloud',
'purpose' => 'Web Search'
),
'Example Down Host' => array(
'ip' => 'example.com',
'port' => 8091,
'info' => 'ShittyWebHost3',
'purpose' => 'No purpose'
)
);
Result:
array(2) {
["Google Web Search"]=>
array(4) {
["ip"]=>
string(0) ""
["port"]=>
int(80)
["info"]=>
string(19) "Hosted by The Cloud"
["purpose"]=>
string(10) "Web Search"
}
["Example Down Host"]=>
array(4) {
["ip"]=>
string(11) "example.com"
["port"]=>
int(8091)
["info"]=>
string(14) "ShittyWebHost3"
["purpose"]=>
string(10) "No purpose"
}
}
I put this data in a database and want to make the same array but i dont seem to get it working
This is the code i added to make an array:
$query ="SELECT name, ip, port, hosting FROM sites";
$select = $conn->prepare($query);
$select->execute(array());
$testing = array();
while($rs = $select->fetch(PDO::FETCH_ASSOC)) {
$testing[] = array($rs['name'] => array('ip'=> $rs['ip'], 'port'=> $rs['port'], 'hosting'=> $rs['hosting']));
}
The result from this is:
array(2) {
[0]=>
array(1) {
["Google Web Search"]=>
array(3) {
["ip"]=>
string(10) "google.com"
["port"]=>
string(2) "80"
["hosting"]=>
string(19) "Hosted by The Cloud"
}
}
[1]=>
array(1) {
["Example Down Host"]=>
array(3) {
["ip"]=>
string(11) "example.com"
["port"]=>
string(2) "09"
["hosting"]=>
string(14) "ShittyWebHost3"
}
}
}
is there a way to make the bottom array the same as the top array, i dont want to edit the whole script, this seems easier.
You are appending a new integer indexed element with [] and then adding 2 nested arrays. Instead, add the name as the key:
$testing[$rs['name']] = array('ip'=> $rs['ip'],
'port'=> $rs['port'],
'hosting'=> $rs['hosting']);
Since you specify the columns in the query and they are the same as the array keys, then just this:
$testing[$rs['name']] = $rs;
When you assign a value to an array you use the syntax $arr[key] = $value. If you omit the key during the assignment, $value will be assigned to the next available integer key of the array, starting from 0.
This is an example of how it works:
$arr = array();
$arr[] = 'one';//Empty, so insert at 0 [0=>'one']
$arr[] = 'two';//Last element at 0, so use 1 [0=>'one',1=>'two']
$arr[6]= 'three';//Key is used, so use key [0=>'one',1=>'two',6=>'three']
$arr[] = 'four';//Max used integer key is 6, so use 7
print_r($arr);//[0=>'one',1=>'two',6=>'three',7=>'four']
So, when in your code you are using
$testing[] = array(
$rs['name'] => array(
'ip'=> $rs['ip'],
'port'=> $rs['port'],
'hosting'=> $rs['hosting']
)
);
You are assigning the newly created array to the positions 0,1,2,..N.
To avoid this, just specify the key explicitly, using the value you really want, like
$testing['name'] => array(
'ip'=> $rs['ip'],
'port'=> $rs['port'],
'hosting'=> $rs['hosting']
);
You can read more about arrays in the documentation
Side note
If you don't mind having an extra column in the generated arrays, you can rewrite entirely your code this way:
$query ="SELECT name, ip, port, hosting FROM sites";
$results = $conn->query($query)->fetchAll(PDO::FETCH_ASSOC);
$testing = array_column($results,null,'name');
It's slightly slower, but very handy in my opinion, PDOStatement::fetchAll retrieves all the data at once and array_column using null as second parameter does reindex the array with the wanted column as key.
PDOStatement::fetchAll
array_column

PHP Array doesn't show all items

I have this code for an array, and the problem is that it shows only two last items of the array.
$svi= array(
$WMN1,
$LNG1,
$SSWN1,
$DT1,
$OET1,
$OW1,
$NT1
);
$imena_sajtova = array(
'Prvi WMN',
'Drugi LNG',
'Treci SSWN',
'Cetvrti DT',
'Peti OET',
'Sesti OW',
'Sedmi NT'
);
$novi_svi =array_combine($svi, $imena_sajtova);
echo '<pre>'; print_r($novi_svi); echo '</pre>';
And the result of this code is:
Array
(
[2] => Sedmi NT
[1] => Sesti OW
)
What could be a problem? Thanks!
var_dump($svi) displays this:
array(7) { [0]=> int(2) [1]=> int(1) [2]=> int(1) [3]=> int(1) [4]=> int(2) [5]=> int(1) [6]=> int(2) }
This $svi array has results from some functions:
$WMN1=RSS_Brojac($WMN);
$LNG1=RSS_Brojac($LNG);
$SSWN1=RSS_Brojac($SSWN);
$DT1=RSS_Brojac($DT);
$OET1=RSS_Brojac($OET);
$OW1=RSS_Brojac($OW);
$NT1=RSS_Brojac($NT);
I've changed order of arrays in the array_combine, and it works!
$novi_svi =array_combine($imena_sajtova, $svi);
arsort($novi_svi);
echo '<pre>'; print_r($novi_svi); echo '</pre>';
And the output of this code is:
Array
(
[Prvi WMN] => 2
[Sedmi NT] => 2
[Peti OET] => 2
[Sesti OW] => 1
[Cetvrti DT] => 1
[Drugi LNG] => 1
[Treci SSWN] => 1
)
I'have sorted them from high to low, that's what I actually wanted to do with this array.
Now, how to separate the results, to have them in separate divs inside html?
So then, I'll be able to change their style and create some kind of table with these results.
The results are output from some RSS feeds, which I use to count number of published news.
Thank you for your time!
Well there you go, the exact reason why you only retrieve two values after the array combine is because you've only supplied two unique integers, 1,2 as the indexes of the arrays to be combined. You need at least 7 unique values for your 7 strings.
Here's an example using your code and it doesn't work
And...Here's an example using 7 unique indexes, that does work
Typecast the values in the first array before merge. Can be achieved with array_map(). I assume you know the desired types in the variables.

Trouble with PHP array_diff

We upload a lot of photos to WordPress. We do not use them all though. The unused ones remain "attached" to the post it's not in which makes it hard to go back and delete it.
I've build 2 arrays. One array contains all of the images from the post content ($postImages). The other array contains all of the images WordPress database have attached to the post ($mediaImages).
I'm trying to identify which images appear in the database, but not in the post. This way I can detach the image from within the database.
I'm using array_diff to compare the two arrays, however it's not showing the odd man out. It appears to be showing the matches.
Here's my arrays:
Call this one $postImages:
var_dump($postImages);
array(3) {
[2]=>
string(64) "http://mywebsite.com/wp-content/uploads/2013/11/photoblog1.jpg"
[0]=>
string(64) "http://mywebsite.com/wp-content/uploads/2013/11/photoblog2.jpg"
[1]=>
string(64) "http://mywebsite.com/wp-content/uploads/2013/11/photoblog3.jpg"
}
And $mediaImages:
var_dump($mediaImages);
array(4) {
[1]=>
array(1) {
[0]=>
string(64) "http://mywebsite.com/wp-content/uploads/2013/11/photoblog1.jpg"
}
[2]=>
array(1) {
[0]=>
string(64) "http://mywebsite.com/wp-content/uploads/2013/11/photoblog2.jpg"
}
[0]=>
array(1) {
[0]=>
string(64) "http://mywebsite.com/wp-content/uploads/2013/11/photoblog3.jpg"
}
[3]=>
array(1) {
[0]=>
string(62) "http://mywebsite.com/wp-content/uploads/2013/12/IMG_0069.jpg"
}
}
Here is the output:
$matches = array_diff($postImages, $mediaImages);
print_r($matches);
Array
(
[2] => http://mywebsite.com/wp-content/uploads/2013/11/photoblog1.jpg
[0] => http://mywebsite.com/wp-content/uploads/2013/11/photoblog2.jpg
[1] => http://mywebsite.com/wp-content/uploads/2013/11/photoblog3.jpg
)
Expected output:
Array
(
[0] => http://mywebsite.com/wp-content/uploads/2013/12/IMG_0069.jpg
)
As Marc B pointed out in the comments, $mediaImages is an array of arrays of strings, while $postimages is just an array of strings.
You can use array_map() with a custom callback to create the $mediaImages array:
$mediaImages = array_map(function($item) {
return $item[0];
}, $mediaImages);
Also, note that you have the parameters for array_diff() backwards. The correct order is:
array_diff($arrayToCompareFrom , $arrayToCompareAgainst);
So to compare $postImages against $mediaImages, you'd need:
$matches = array_diff($mediaImages, $postImages);
print_r($matches);
Demo.

Push value to array

I have an array with multiple values and need to push a value into this array.
The orignial array looks like:
[0]=> array(2) { ["name"]=> string(17) "Name" ["id"]=> string(8) "134567" }
[1]=> array(2) { ["name"]=> string(13) "Name" ["id"]=> string(9) "123456" }
And I need to put these values into the above array:
$personal['id']
$personal['name']
How can this be done?
Use square bracket notation to append to the original array:
$original[] = $person;
Or if $person is more complex and you only want those two keys:
$original[] = array(
'name' => $personal['name'],
'id' => $personal['id']);
Assuming that the $personal array only contains id and name you could use array_push.
array_push($array, $personal);
Seems that the guy who gave me the answer deleted his answer,
But this I used to add values to
$originalArray[]['id'] = $personal['id'];
$originalArray[]['name'] = $personal['name'];
Anyway ++1 for you, thanks! :)
See if this works for you:
$yourarray[]=$personal;

Push Associate array into another array

I would like to push an associate array into another array but I an not sure how to go about it. At the minute I have the following:
$rate_info = array(
"hotel_rating" => $hotel->{'hotelRating'},
"room_rate" => $hotel->{'RoomRateDetailsList'}->{'RoomRateDetails'}->{'RateInfo'}->{'ChargeableRateInfo'}->{'#total'},
"currency" => $hotel->{'RoomRateDetailsList'}->{'RoomRateDetails'}->{'RateInfo'}->{'ChargeableRateInfo'}->{'#currencyCode'},
"deep_link" => $hotel->{'deepLink'}
);
array_push($hotel_array[$hotel->{'name'}]["offers"], "expedia" => $rate_info );
"Offers" is an array , all I want to do is add an key value with an array within in. Any ideas? All I seem to be getting at the minute is parse errors.
UPDATE
This is the output of the array so far
["offers"]=>
array(2) {
["LateRooms"]=>
array(4) {
["hotel_rating"]=>
int(4)
["room_rate"]=>
string(6) "225.06"
["currency"]=>
string(3) "USD"
}
[0]=>
string(4) "test"
}
As you can see instad of [0] I would like ["site"]=>array()
Thanks
Oliver
I'd do this for the array assignment:
$hotel_array[$hotel->name]['offers']['expedia'] = $rate_info;
Ensure your warnings are enabled, so you know arrays (and subarrays) have been set up before you use them.
Did you first do this?
$hotel_array[$hotel->{'name'}] = array();
And then you can do:
array_push($hotel_array[$hotel->{'name'}]["offers"], "expedia" => $rate_info );

Categories