Sort an array of objects by fields - php

i would like to sort the following tab by the "date" field and calculate the sum of the "temps" field :
0 => array (size=3) 'id_cra' => string '4586' (length=4) 'temps' => string '03:00:00' (length=8) 'date' => string '2013-06-03' (length=10)
1 => array (size=3) 'id_cra' => string '4587' (length=4) 'temps' => string '03:00:00' (length=8) 'date' => string '2013-06-06' (length=10)
2 => array (size=3) 'id_cra' => string '4588' (length=4) 'temps' => string '03:00:00' (length=8) 'date' => string '2013-06-05' (length=10)
3 => array (size=3) 'id_cra' => string '4589' (length=4) 'temps' => string '03:00:00' (length=8) 'date' => string '2013-06-06' (length=10)
4 => array (size=3) 'id_cra' => string '4590' (length=4) 'temps' => string '03:00:00' (length=8) 'date' => string '2013-06-07' (length=10)
5 => array (size=3) 'id_cra' => string '4591' (length=4) 'temps' => string '02:00:00' (length=8) 'date' => string '2013-06-03' (length=10)
6 => array (size=3) 'id_cra' => string '4592' (length=4) 'temps' => string '03:30:00' (length=8) 'date' => string '2013-06-03' (length=10)
The expected result :
date = > Sum of the "Temps" fields
2013-06-03 =>08:30:00
2013-06-06 =>06:00:00
etc
PS: Sorry for asking something that might be simple for you, i already checked on internet (for instance here : Sort array of objects by object fields) but i don't understand the answer

I didn't try, but it has to be something like this:
$arr = [your array data]; // your array which has to be sorted
usort($arr, 'sort_array');
function sort_array($a, $b) {
$timeA = strtotime($a['date']);
$timeB = strtotime($b['date']);
if($timeA == $timeB) {
return 0;
}
return $timeA < $timeB ? -1 : 1;
}
calculating the sums would be a loop after sorting the array where you have to "group" by date and sum the "temps"

The first part is fairly simple. We can sort the data for an array by a field using array_multisort() like so:
<?php
$data = array(
0 => array('id_cra' => '4586', 'temps' => '03:00:00', 'date' => '2013-06-03'),
1 => array('id_cra' => '4587', 'temps' => '03:00:00', 'date' => '2013-06-06'),
2 => array('id_cra' => '4588', 'temps' => '03:00:00', 'date' => '2013-06-05'),
3 => array('id_cra' => '4589', 'temps' => '03:00:00', 'date' => '2013-06-06'),
4 => array('id_cra' => '4590', 'temps' => '03:00:00', 'date' => '2013-06-07'),
5 => array('id_cra' => '4591', 'temps' => '02:00:00', 'date' => '2013-06-03'),
6 => array('id_cra' => '4592', 'temps' => '03:30:00', 'date' => '2013-06-03')
);
$tmp = array();
foreach($data as $k=>$r){
$tmp[] = $r['date'];
}
array_multisort($tmp,SORT_DESC,$data);
echo '<pre>',print_r($data),'</pre>';
But now want to add the times for each of the days. This isn't difficult, but you will lose the id_cra values. So for the example below I have just created a new array. You should be able to use the information to build it back into your original array if that what you want to do.
date_default_timezone_set('America/New_York'); //set timezone
$midnight = mktime(0,0,0,date("n"),date("j"),date("Y")); // create a constant
$times = array();
foreach($data as $d){
// get number of secs since const
$time = strtotime(date("Y-m-d",$midnight).' '.$d['temps']) - $midnight;
if(isset($times[$d['date']])){
$times[$d['date']] += $time; // if day exists add secs
}else{
$times[$d['date']] = $time; // else set day with cur secs
}
}
foreach($times as $k=>&$time){
$time = date("Y-m-d H:i:s",strtotime($k)+$time); // reformat to date
}
echo '<pre>',print_r($times),'</pre>';

Related

Sorting 'key=>value' pair multi-dimensional arrays in PHP

I am creating a site and I am trying to do a few complicated things with arrays to get it to work.
It is for an e-commerce site and each product on my site can have a number of attributes. I am trying to get each combination of attributes to do the pricing for them seperately.
First I get an array of the attribute ids ($attribute_id_array) and the query the database for the options for that array.
So if one attribute was colors the options here would be red,green,blue,etc,. or size would be small,medium,large,etc,. These are then stored in a new array ($attribute_arrays).
I then go through these to get every combination of attributes the product can have and sort these into a new array again ($new_attributes_array).
I then loop through this and create a price form for each combination.
$attribute_arrays = [];
foreach($attribute_id_array as $attribute_id){
$params = [$attribute_id];
$sql = "SELECT * FROM attributes WHERE id=?";
$attributeResult = DB::run($sql,$params);
while($row = $attributeResult->fetch(PDO::FETCH_ASSOC)){
array_push($attribute_arrays,$row);
}
}
var_dump($attribute_arrays);
function combinations($arrays, $i = 0) {
if (!isset($arrays[$i])) {
return array();
}
if ($i == count($arrays) - 1) {
return $arrays[$i];
}
$tmp = combinations($arrays, $i + 1);
$result = array();
foreach ($arrays[$i] as $v) {
foreach ($tmp as $t) {
$result[] = is_array($t) ?
array_merge(array($v), $t) :
array($v, $t);
}
}
return $result;
}
$new_attributes_array = combinations($attribute_arrays);
var_dump($new_attributes_array);
This is all working fine except I want to be able to get the keys for all of the key value pairs so I can reference it back to my database.
The way it comes out at the moment is like this:
$attribute_id_array:
array (size=2)
1 => string '5' (length=1)
2 => string '7' (length=1)
$attribute_arrays:
0 =>
array (size=2)
'attribute1' => string 'Step Through Bars' (length=17)
'attribute2' => string 'Gated' (length=5)
1 =>
array (size=2)
'attribute1' => string '3 metres' (length=8)
'attribute2' => string '6 metres' (length=8)
$new_attributes_array:
0 =>
array (size=2)
0 => string 'Step Through Bars' (length=17)
1 => string '3 metres' (length=8)
1 =>
array (size=2)
0 => string 'Step Through Bars' (length=17)
1 => string '6 metres' (length=8)
2 =>
array (size=2)
0 => string 'Gated' (length=5)
1 => string '3 metres' (length=8)
3 =>
array (size=2)
0 => string 'Gated' (length=5)
1 => string '6 metres' (length=8)
Is there a way to get it so that the key will be similar in format to:
0 =>
array (size=2)
5-attribute1 => string 'Step Through Bars' (length=17)
7-attribute1 => string '3 metres' (length=8)
1 =>
array (size=2)
5-attribute1 => string 'Step Through Bars' (length=17)
7-attribute2 => string '6 metres' (length=8)
Edit
So I changed the line array_push($attribute_arrays,$row); to $attribute_arrays[$attribute_id] = $row;.
This now means that $attribute_arrays now has the$attribute_id variable as the key like so:
array (size=2)
5 =>
array (size=2)
'attribute1' => string 'Step Through Bars' (length=17)
'attribute2' => string 'Gated' (length=5)
7 =>
array (size=2)
'attribute1' => string '3 metres' (length=8)
'attribute2' => string '6 metres' (length=8)
This now means my other function for getting the combinations won't work as it is using the $i variable as the index for the array starting at '0'.
Found another function online to sort it here How to generate in PHP all combinations of items in multiple arrays:
function combinations($arrays) {
$result = array(array());
foreach ($arrays as $property => $property_values) {
$tmp = array();
foreach ($result as $result_item) {
foreach ($property_values as $property_key => $property_value) {
$tmp[] = $result_item + array($property_key => $property_value);
}
}
$result = $tmp;
}
return $result;
}
However, this doesn't do exactly as I want and I end up with this:
array (size=4)
0 =>
array (size=1)
'attribute1' => string 'Step Through Bars' (length=17)
1 =>
array (size=2)
'attribute1' => string 'Step Through Bars' (length=17)
'attribute2' => string '6 metres' (length=8)
2 =>
array (size=2)
'attribute2' => string 'Gated' (length=5)
'attribute1' => string '3 metres' (length=8)
3 =>
array (size=1)
'attribute2' => string 'Gated' (length=5)
try this as your combinations function
modified code taken from here
function combinations($arrays) {
$result = array(array());
foreach ($arrays as $key => $values) {
$tmp = array();
foreach ($result as $item) {
foreach ($values as $k=>$value) {
$tmp[] = array_merge($item, array($key.'-'.$k => $value));
}
}
$result = $tmp;
}
return $result;
}
Instead of using while on following line
while($row = $attributeResult->fetch(PDO::FETCH_ASSOC)){
Use foreach loop to get key paired value. e.g
foreach($databaseFetchedRecord as $mykey=>$myvalue)

Convert array index to custom value?

I have an array $indexedarray
printr($indexedarray) gives something like this
array (size=3)
0 => string 'Homes' (length=5)
1 => string 'Apartments' (length=10)
2 => string 'Villas' (length=6)
I want to change this arrays index also same as value, like
array (size=3)
'Homes' => string 'Homes' (length=5)
'Apartments' => string 'Apartments' (length=10)
'Villas' => string 'Villas' (length=6)
is it posssible??
You can use array_combine:
$indexedarray= ['Homes', 'Apartments', 'Villas'];
print_r(array_combine($indexedarray, $indexedarray));
Gives:
Array
(
[Homes] => Homes
[Apartments] => Apartments
[Villas] => Villas
)
But be aware that your duplicate values will be dropped. Keys will be unique!
Try This :
$myArray = [
0 => 'Homes',
1 => 'Apartments',
2 => 'Villas' ];
$newArray = [];
foreach($myArray as $key => $value){
$newArray[$value] = $value;
}
var_dump($newArray);

How to display array value separately with selected column?

I want to display array 1 by 1.. 1st array value display thnn 2nd array value
I want to display array data using loop and display data separatelylike 1st array data display then 2nd array data will display. and i want to display data only entrydate n description. with loop count
$svs= $user_posts->getvalue('service', $dsplylimit );
var_dump($svs);
My array is like this
array (size=2)
0 =>
array (size=46)
0 => string '74' (length=2)
'id' => string '74' (length=2)
1 => string '0' (length=1)
'author' => string '0' (length=1)
2 => string '2016-02-08 07:32:08' (length=19)
'entrydate' => string '2016-02-08 07:32:08' (length=19)
3 => string '2016-02-08 01:32:08' (length=19)
'date_gmt' => string '2016-02-08 01:32:08' (length=19)
4 => string 'nice email' (length=10)
'description' => string 'nice email' (length=10)
1 =>
array (size=46)
0 => string '75' (length=2)
'id' => string '75' (length=2)
1 => string '0' (length=1)
'author' => string '0' (length=1)
2 => string '2016-02-08 11:15:40' (length=19)
'entrydate' => string '2016-02-08 11:15:40' (length=19)
3 => string '2016-02-08 05:15:40' (length=19)
'date_gmt' => string '2016-02-08 05:15:40' (length=19)
4 => string 'hiiiiiii' (length=8)
'description' => string 'hiiiiiii' (length=8)
It isn't very clear what you want to do, but you can probably display the data with a foreach loop. Just loop through each array, and then print out the values from each iteration that you want.
For example for the following array
$data = [
['entrydate' => '2016-01-01', 'description' => 'Some description here'],
['entrydate' => '2016-01-02', 'description' => 'Another description here']
];
You could print out the data like so:
$html = '';
foreach ($data as $array) {
$html .= '<h1>' . htmlspecialchars($array['entrydate']) . '</h1>';
$html .= '<p>' . htmlspecialchars($array['description']) . '</p>';
}
echo $html;
For the following output:
2016-01-01
Some description here
2016-01-02
Another description here
There's a chance I'm not understanding your requirements, if so just let me know, but I'm not 100% sure what it is you're after.

Add entries together based on key in array PHP

As you can see I have a key called dateTime which holds dates. What I need to do is add all the entries together for each date and return the array. So I simply got one dateTime per date with all the entries of that day added together. I do not know the dateTime inputs ahead of time as I have a crawler that constantly inserts data into my database.
How would you go about doing that in the most efficient way? I imagine I would have to do a foreach loop and somehow check if the key value (dateTime) changes from the previous key value. And then create a brand new array that I return
An example of the array is as follows:
array (size=130)
0 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '225' (length=3)
1 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '218' (length=3)
2 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '217' (length=3)
3 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '225' (length=3)
4 =>
array (size=2)
'dateTime' => string '2015-09-02' (length=10)
'entries' => string '231' (length=3)
5 =>
array (size=2)
'dateTime' => string '2015-09-02' (length=10)
'entries' => string '220' (length=3)
6 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '223' (length=3)
7 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '237' (length=3)
8 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '220' (length=3)
So it returns an array like this
array (size=130)
0 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '660' (length=3)
1 =>
array (size=2)
'dateTime' => string '2015-09-02' (length=10)
'entries' => string '451' (length=3)
2 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '680' (length=3)
Edit With the help of you guys, I ended up doing the following to get the right format.
function prepareArrayForGraphDates($array){
$results = [];
$finalResult = [];
foreach ($array as $value) {
if (!isset($results[$value['dateTime']])) {
$results[$value['dateTime']] = 0;
}
$results[$value['dateTime']] += $value['entries'];
}
$keyNames = array_keys($results);
for ($x = 0; $x < sizeof($results); $x++) {
$finalResult[$x]['dateTime'] = $keyNames[$x];
$finalResult[$x]['entries'] = $results[$keyNames[$x]];
}
return $finalResult;
}
Use the fact that array keys are unique...
$results = [];
foreach ($array as $value) {
if (!isset($results[$value['dateTime']])) {
$results[$value['dateTime']] = 0;
}
$results[$value['dateTime']] += $value['entries'];
}
You can use an array like a set or a dictionary, using the date as the key.
$data = [
[
'datetime'=>'2015-09-02',
'entries' => 220
]
// ... other entries snipped ...
];
$results = [];
foreach ($data as $date => $entry)
{
// if the date has already been recorded with an initial value, add to it
if (array_key_exists($date, $results) {
$results[$date] += $entry
} else {
// the date is new; add it to the results and set its initial value
$results[$date] = $entry;
}
}

Split Array at Repeating Object in Array

I am parsing an XML file and creating two arrays: one of the XML tags ($tags), and the other as the values for the tags ($values). As it parses, it adds the tags and values as it goes, when it's done, I implode the arrays and put them into a MySQL statement:
$sql = "INSERT INTO everything ($tags) VALUE ($values)";
This works fine until I have repeating tags, and then the SQL statement doesn't work....
Is there a way to find the first repeated word in the $tags array and split it at that word (Keeping the tags that follow it) and also split the $values array at the same index that $tags was split, so that the information stays in the same order?
So ultimately converting something like this:
INSERT INTO everything (AmazonOrderID,MerchantOrderID,ShipmentID,MerchantFulfillmentID,PostedDate,AmazonOrderItemCode,SKU,Quantity,Principal,Commission,AmazonOrderItemCode,SKU,Quantity,Principal,Commission,AmazonOrderItemCode,SKU,Quantity,Principal,Commission,FBA) VALUE ('1','1','D','A','2015','64','OX','1','18','-2','64','WA','1','23','-2','29','WAG','1','49','77','97');
Into something like:
INSERT INTO everything (AmazonOrderID,MerchantOrderID,ShipmentID,MerchantFulfillmentID,PostedDate,AmazonOrderItemCode,SKU,Quantity,Principal,Commission) VALUES ('1','1','D','A','2015','64','OX','1','18','-2');
INSERT INTO everything (AmazonOrderItemCode,SKU,Quantity,Principal,Commission) VALUES ('64','WA','1','23','-2');
INSERT INTO everything (AmazonOrderItemCode,SKU,Quantity,Principal,Commission,FBA) VALUES ('29','WAG','1','49','77','97');
Thanks in advance!...
I just base from your "something like".. :)
$fields = ['AmazonOrderID', 'MerchantOrderID', 'ShipmentID', 'MerchantFulfillmentID', 'PostedDate', 'AmazonOrderItemCode', 'SKU', 'Quantity', 'Principal', 'Commission', 'AmazonOrderItemCode', 'SKU', 'Quantity', 'Principal', 'Commission', 'AmazonOrderItemCode', 'SKU', 'Quantity', 'Principal', 'Commission', 'FBA'];
$values = ['1','1','D','A','2015','64','OX','1','18','-2','64','WA','1','23','-2','29','WAG','1','49','77','97'];
// i just added this to avoid error produced by: `Undefined offset` error warning
error_reporting(0);
$fields_dup = array();
$values_dup = array();
for ($i = 0, $j = 0; $i < count($fields); $i++)
{
if (in_array($fields[$i], $fields_dup[$j]))
$j++;
$fields_dup[$j][] = $fields[$i];
$values_dup[$j][] = $values[$i];
// or maybe you want to add ` and ' make your statement look like:
// INSERT INTO table (`field1`, `field2`) VALUES ('value1', 'value2')
//
// $fields_dup[$j][] = "`".$fields[$i]."`";
// $values_dup[$j][] = "'".$values[$i]."'";
}
error_reporting(E_ALL);
// just to show what is produced
var_dump($fields_dup);
var_dump($values_dup);
// while you can also construct your statement in a loop like
for ($i = 0; $i < count($fields_dup); $i++)
{
$sql_fields = implode(',', $fields_dup[$i]);
$sql_values = implode(',', $values_dup[$i]);
echo "INSERT INTO everything ($sql_fields) VALUES ($sql_values) <br>";
}
Output would be:
//var_dump($fields_dup);
array (size=3)
0 =>
array (size=10)
0 => string 'AmazonOrderID' (length=13)
1 => string 'MerchantOrderID' (length=15)
2 => string 'ShipmentID' (length=10)
3 => string 'MerchantFulfillmentID' (length=21)
4 => string 'PostedDate' (length=10)
5 => string 'AmazonOrderItemCode' (length=19)
6 => string 'SKU' (length=3)
7 => string 'Quantity' (length=8)
8 => string 'Principal' (length=9)
9 => string 'Commission' (length=10)
1 =>
array (size=5)
0 => string 'AmazonOrderItemCode' (length=19)
1 => string 'SKU' (length=3)
2 => string 'Quantity' (length=8)
3 => string 'Principal' (length=9)
4 => string 'Commission' (length=10)
2 =>
array (size=6)
0 => string 'AmazonOrderItemCode' (length=19)
1 => string 'SKU' (length=3)
2 => string 'Quantity' (length=8)
3 => string 'Principal' (length=9)
4 => string 'Commission' (length=10)
5 => string 'FBA' (length=3)
// var_dump($values_dup);
array (size=3)
0 =>
array (size=10)
0 => string '1' (length=1)
1 => string '1' (length=1)
2 => string 'D' (length=1)
3 => string 'A' (length=1)
4 => string '2015' (length=4)
5 => string '64' (length=2)
6 => string 'OX' (length=2)
7 => string '1' (length=1)
8 => string '18' (length=2)
9 => string '-2' (length=2)
1 =>
array (size=5)
0 => string '64' (length=2)
1 => string 'WA' (length=2)
2 => string '1' (length=1)
3 => string '23' (length=2)
4 => string '-2' (length=2)
2 =>
array (size=6)
0 => string '29' (length=2)
1 => string 'WAG' (length=3)
2 => string '1' (length=1)
3 => string '49' (length=2)
4 => string '77' (length=2)
5 => string '97' (length=2)
// for the last for-statement
INSERT INTO everything (AmazonOrderID,MerchantOrderID,ShipmentID,MerchantFulfillmentID,PostedDate,AmazonOrderItemCode,SKU,Quantity,Principal,Commission) VALUES (1,1,D,A,2015,64,OX,1,18,-2)
INSERT INTO everything (AmazonOrderItemCode,SKU,Quantity,Principal,Commission) VALUES (64,WA,1,23,-2)
INSERT INTO everything (AmazonOrderItemCode,SKU,Quantity,Principal,Commission,FBA) VALUES (29,WAG,1,49,77,97)
Is that what you are trying to do?
Hope this is helpful, Cheers! ;)

Categories