Consolidating specific values in multidimensional array - php

I have an array of arrays consisting of date, login name, and time (length of time in ms). Here is what it vaguely looks like:
[0]=>
[0]=> "2015-09-06"
[1]=> "user1"
[2]=> "8947226"
[1]=>
[0]=> "2015-09-06"
[1]=> "user1"
[2]=> "6664923"
[2]=>
[0]=> "2015-09-24"
[1]=> "user2"
[2]=> "654654"
I'm trying to make it so that if the date and the login are both the same as another, it adds the time together. So it will look like:
[0]=>
[0]=> "2015-09-06"
[1]=> "user1"
[2]=> "15612149"
[1]=>
[0]=> "2015-09-24"
[1]=> "user2"
[2]=> "654654"
I think my main problem is how to search the array because they won't necessarily be in order by date or login, they're all random.
First I was doing this because I thought they would be in some sort of order:
if ($i != 0) {
if ($date == $bigArray[$prevIndex][0] && $login == $bigArray[$prevIndex][1]) {
$bigArray[$prevIndex][2] += $time;
} else {
array_push($bigArray, array($date, $login, $time));
$prevIndex++;
}
} else {
array_push($bigArray, array($date, $login, $time));
}
But that doesn't work since they are in a random order. I've tried to sort the array first as well, and that's not working.

There's a way to do it, but maybe it's not the best.
<?php
$arr = [];
$arr[0] = ["2015-09-26", "user1", "8947226"];
$arr[1] = ["2015-09-26", "user1", "6664923"];
$arr[2] = ["2015-09-24", "user2", "654654"];
// Variable to store the new values.
$arr2 = [];
// Scrolls through the array
foreach($arr as $ar) {
// Creates a key to identify date and login
$key = md5($ar[0].$ar[1]);
// Checks whether the value is already in the variable $arr2
if (isset($arr2[ $key ])) {
// If so, adds the values in ms
$arr2[ $key ][2] += $ar[2];
} else {
$arr2[ $key ] = $ar;
}
}
// Use the array_values to display only the values (without displaying the $key);
var_export( array_values($arr2) );

Related

PHP Arrays - Merge two arrays where a value is added together

I need some more help regarding PHP Arrays and the issue I am having. I have an array like this: -
array(2) {
[0]=>
array(2) {
[0]=>
array(2) {
["count"]=>
string(3) "100"
["id"]=>
int(46)
}
[1]=>
array(2) {
["count"]=>
string(3) "300"
["id"]=>
int(53)
}
}
[1]=>
array(1) {
[0]=>
array(2) {
["count"]=>
string(3) "200"
["id"]=>
int(46)
}
}
}
However, I would like it to look more like this as array: -
array(2) {
[0]=>
array(2) {
["count"]=>
string(3) "300" <--- This has been added from Array 1 and 2
["id"]=>
int(46)
}
[1]=>
array(2) {
["count"]=>
string(3) "300"
["id"]=>
int(53)
}
}
Basically if the same id is in both areas I want the count number to be added to each other but if it's not then it needs to just be left alone and included in the array.
I have used a number of array functions such as array_merge and array_push but I am running out of ideas of how this could work. I have also started working on a foreach with if statements but I just got myself completely confused. I just need a second pair of eyes to look at the issue and see howe it can be done.
Thanks again everyone.
Should work with something like this:
$idToCountArray = array(); //temporary array to store id => countSum
array_walk_recursive($inputArray, function($value,$key) { //walk each array in data structure
if(isset(value['id']) && isset($value['count'])) {
//we have found an entry with id and count:
if(!isset($idToCountArray[$value['id']])) {
//first count for id => create initial count
$idToCountArray[$value['id']] = intval($value['count']);
} else {
//n'th count for id => add count to sum
$idToCountArray[$value['id']] += intval($value['count']);
}
}
});
//build final structure:
$result = array();
foreach($idToCountArray as $id => $countSum) {
$result[] = array('id' => $id, 'count' => ''.$countSum);
}
Please note that I have not testet the code and there is probably a more elegant/performant solution.
You could use something like this:
$end_array = array();
function build_end_array($item, $key){
global $end_array;
if (is_array($item)){
if( isset($item["id"])){
if(isset($end_array[$item["id"]]))
$end_array[$item["id"]] = $end_array[$item["id"]] + $item["count"]*1;
else
$end_array[$item["id"]] = $item["count"]*1;
}
else {
array_walk($item, 'build_end_array');
}
}
}
array_walk($start_array, 'build_end_array');
Here is a fiddle.
Thank you ever so much everyone. I actually worked it by doing this: -
$fullArray = array_merge($live, $archive);
$array = array();
foreach($fullArray as $key=>$value) {
$id = $value['id'];
$array[$id][] = $value['count'];
}
$result = array();
foreach($array as $key=>$value) {
$result[] = array('id' => $key, 'count' => array_sum($value));
}
return $result;

How to make an average of array values

I have a database with multiple records. It is structured like this:
["data"]=>
array(5) {
[1]=>
[2]=>
array(11) {
[0]=>
string(1) "0"
[1]=>
string(8) "25000000"
[2]=>
string(3) "day"
[3]=>
string(5) "0.00%"
[4]=>
string(9) "404049904"
[5]=>
string(1) "0"
[6]=>
string(5) "0.00%"
[7]=>
string(1) "0"
[8]=>
string(1) "0"
[9]=>
string(1) "0"
[10]=>
string(3) "0.0"
}
I need to fetch the 8th record and I do this by using
public static function($data)
{
$array = [];
$path = $data->data[2];
foreach($path as $key => $item)
if($key > 1)
{
$array[] = [$item->data[8]];
}
return json_encode($array);
}
This foreach takes all the 8th values from the array but I need to display a single number which is the average of all the 8th values. How can I do this?
Once you've got your array containing all your data, simple sum the array and then divide by the size of the array.. something along these lines
$average = (array_sum($array) / count($array));
Of course you may want to check for count($array) being 0;
Because you put your value into a new array, you can not use array_sum to sum the values, so you should store it.
$sum = 0;
foreach($path as $key => $item)
if($key > 1) {
$array[] = [$item->data[8]];
$sum += $item->data[8];
}
}
$avg = ($sum / count($array); //the average
var_dump($avg);
If is it possible, just put it as a value:
$array[] = $item->data[8]; //no wrapping []
In this case, you can use $avg = array_sum($array) / count($array);
if (count($array)>0){
$avg = array_sum($array) / count($array);
}
I would personally do those calculations in the database before the data gets to your PHP script itself. See AVG().
If you can't for some reason use that I would output those values into a flat array and then just calculate the average. So something like :
function getAverage($data) {
$flatArray = array();
foreach ($data as $row) {
if (!empty($row->8)) {
$flatArray[] = $row->8;
}
}
return (array_sum($flatArray)/count($flatArray));
}
EDIT: Moved to Object traversing on the data row, sorry, missed that initially and thought it was an array in all the nests.
Since you have a loop within your static Method; why not do the calculation therein and return it or add it to the JSON Data if You need your Data in JSON Format? Here's what's implied by the above:
public static function getAverageSum($data) {
$array = [];
$path = $data->data[2];
$sumTotal = 0.00; //<== YOU COULD JUST SUM IT DIRECTLY WITHOUT USING AN ARRAY
foreach($path as $key => $item) {
if ($key > 1) {
$array[] = $item->data[8];
$sumTotal += floatval($item->data[8]);
}
}
// IF YOU ARE ONLY INTERESTED IN THE AVERAGE SUM YOU COULD EVEN ADD IT IT TO THE $array AS AN EXTRA KEY
// LIKE SO:
$arrLen = count($array);
$array['avgSum'] = $sumTotal/$arrLen;
// IF YOU NEED YOUR DATA IN JSON... THEN RETURN THE JSON ENCODED DATA WITH SUM AS PART OF THE DATA.
// YOU'D HAVE NO NEED FOR array_sum() SINCE YOU DID YOUR PREP-WORK ALREADY...
return json_encode($array);
// ALTERNATIVELY; IF ALL YOU NEED IS JUST THE AVERAGE SUM; YOU COULD AS WELL DIRECTLY RETURN $sumTotal/$arrLen
return ($sumTotal/$arrLen);
}

How to edit mulltidimensional array elements in php?

this is my array:
$array= array(3) {
[0]=> array(3) { ["name"]=> "one" ["com"]=> "com1" ["id"]=> "1" }
[1]=> array(3) { ["name"]=> "two" ["com"]=> "com2" ["id"]=> "2" }
[2]=> array(3) { ["name"]=> "three" ["com"]=> "com3" ["id"]=> "3" }
I need posibility to change values of name and com for specific id. I try some examples from Stack questions:
1.Link1
foreach($array as &$value){
if($value['id'] == 1){
$value['name'] = 'test';
$value['com'] = 'test';
break; // Stop the loop after we've found the item
}
}
But it don't work. no error but no result too.
2.Link 2
Again,no error message,but no result...
I also try a lot of other examples from Stack but fake,and finaly to write a question..
Buy,
P
Since you are not changing your array value that's why it's-not giving you desired output. Try this:-
foreach($array as $key => &$value){
if($key == 1){
$array[1]['name'] = 'test';// change value to original array
$array[1]['com'] = 'test'; //change value to original array
break; // Stop the loop after we've found the item
}
}
for($i=0;$i<count($array);$i++) {
if($array[$i]['id'] == 1) {
$array[$i]['name'] = 'test';
$array[$i]['com'] = '';
break;
}
}
print_r($array);
If you are able to change the array on creation I would recommend shifting the id to the array's key identifier. Would make life a lot easier to just do:
$array[1]['name'] = 'test';
Otherwise use the for loop posted above and look it up. (Right awnser)

find / select specified ID in array php

i have array with database, and have to select only this items what have "tid" = 1
array(3) {
[1]=>
array(4) {
["tid"]=> "1"
["title"]=> "Google"
["url"]=> "http://google.com/"
["description"]=> "A very efficient search engine."
}
[2]=>
array(4) {
["tid"]=> "2"
["title"]=> "Facebook"
["url"]=> "http://facebook.com/"
["description"]=> "Trade securities, currently supports nearly 1000 stocks and ETFs"
}
[3]=>
array(4) {
["tid"]=> "1"
["title"]=> "Yandex"
["url"]=> "http://yandex.ru/"
["description"]=> "Another efficient search engine popular in Russia"
}
}
how can i select only this items from array what have "tid" = 1?
<?php
$final_arr = array();
foreach($tid_arrs as $tid_arr){
if($tid_arr['tid'] == 1){
$final_arr[] = $tid_arr;
}
}
print_r($final_arr);
?>
$filteredArray = array();
for($i = 0, $end = count($array);$i < $end;i++)
{
if($array[$i]["tid"] === "1")
{
$filderedArray[] = $array[$i];
}
}
That way $filteredArray will contain solely the items with tid 1;
Try array_filter function: http://php.net/manual/en/function.array-filter.php this should help.
print_r(array_filter($array, "filter_function"));
function filter_function($element){
return (int)$element['tid'] === 1;
}
let's say you starting array is $arr.
$result = array();
foreach ($arr as $arrItem) {
if ((array_key_exists('tid', $arrItem)) && ($arrItem['tid'] == "1")){
$result[] = $arrItem;
}
}
$result should be what you are excepted.

Value in array is a string not an integer

I have a multi-dimensional array which I need to pass to Google Charts. The script is called via Ajax, runs three times and then passes back the array encoded with json_encode. I then needed to add headers to the array so I used array_unshift().
Here is the script
$dataArray = array();
$i = 0;
foreach ($arrSiteValue as $key => $value) {
if($i == 3){
break;
}
$dataArray[$key] = $value;
$i ++;
}
array_unshift($dataArray, array("Terms","Visits"));
echo json_encode($php_array);
Here is what is returned:
Note: Where it says (not set) and (not provided), They are correct values for the string and need to be that.
The value of the key should be an integer however it is getting passed back as a string
How can I get it so that the value is added as an integer?
Here is a dummy array (that works) to show what format the array should be outputted like:
$php_array = array(
array('Terms', 'Visits'),
array('test', 90),
array('joke', 90),
array('funny', 11)
);
And this is what this dummy array ouputs (which is how I need it):
*When I change the line to include (int) as recommenced by some of the users here I get this result:
Edit
These are the lines that get the data from the Google Analytics Library:
if (!$_GET["rangeStartDate"]) {
$startDate = date("Y-m-d", mktime(0, 0, 0, date("m")-1, date("d")-1, date("Y")));
$endDate = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d")-1, date("Y")));
} else {
$startDate = $_GET["rangeStartDate"];
$endDate = $_GET["rangeEndDate"];
}
$metrics = "ga:visits";
$dimensions = "ga:keyword";
$filters = "ga:keyword==(not set)";
$optParams = array('dimensions' => $dimensions, 'filters' => $filters);
$arrSiteResults = $service->data_ga->get($ids,$startDate,$endDate,$metrics,$optParams);
$notSetVisits = $arrSiteResults['rows'][0][1];
// Visits and Page Views
$metrics = "ga:visits";
$dimensions = "ga:keyword";
$optParams = array('dimensions' => $dimensions, 'sort' => '-ga:visits', 'max-results' => '12');
$arrSiteResults = $service->data_ga->get($ids,$startDate,$endDate,$metrics,$optParams);
$arrSiteValue = $arrSiteResults['rows'];
Here is var_dump of: $arrSiteValue:
array(12) { [0]=> array(2) { [0]=> string(9) "(not set)" [1]=> string(4) "2582" } [1]=> array(2) { [0]=> string(14) "(not provided)" [1]=> string(4) "1504" } [2]=> array(2) { [0]=> string(10) "compass fm" [1]=> string(3) "149" } [3]=> array(2) { [0]=> string(18) "compass fm grimsby" [1]=> string(2) "25" } [4]=> array(2) { [0]=> string(9) "compassfm" [1]=> string(2) "10" } [5]=> array(2) { [0]=> string(15) "compassfm.co.uk" [1]=> string(1) "9" } [6]=> array(2) { [0]=> string(16) "compass fm radio" [1]=> string(1) "8" } [7]=> array(2) { [0]=> string(18) "grimsby rugby club" [1]=> string(1) "8" } [8]=> array(2) { [0]=> string(13) "compass radio" [1]=> string(1) "7" } [9]=> array(2) { [0]=> string(21) "compass radio grimsby" [1]=> string(1) "5" } [10]=> array(2) { [0]=> string(19) "www.compassfm.co.uk" [1]=> string(1) "5" } [11]=> array(2) { [0]=> string(15) "compass fm news" [1]=> string(1) "4" }}
PHP's json_encode function will always encode PHP strings as JSON strings. If the data goes into JSON as a string, it was a string in PHP as well.
Why it is a string in PHP is an interesting question. Perhaps the data comes from a database?
In any case, the solution is to convert the string into an integer (with (int)) when you pass it to json_encode:
$dataArray[$key] = (int) $value;
NB that I wouldn't check with is_numeric. The API is clearly expecting the value to be an integer, so I'd suggest you provide one. If the value can't be converted, it will be 0, which is probably a sensible default in your case.
OK, the above code is wrong, because it attempts to convert the array into an integer. The problem, then, is how that array is constructed. It's very hard to help you fix this if you can't show the line of code that creates the value that isn't working.
But I'll bet £5 that the solution is (int).
Per the latest update. I hadn't realised the data was coming from Google Analytics. You get the data and it looks like this: [1]=> string(4) "2582". That is obviously a string that contains number characters. You need to convert this to a number using (int). You should do this in your loop:
if($i == 3){
break;
}
$value[1] = (int) $value[1]; // cast the number to an int
$dataArray[$key] = $value;
Try changing assignment line to this:
$dataArray[$key] = is_numeric($value) ? (int)$value : $value;
Note: it's not a generic solution, but will work in this particular case.
Use intval() (assuming they're all integers, otherwise use floatval()).
$dataArray = array();
$i = 0;
foreach ($arrSiteValue as $key => $value) {
if($i == 3){
break;
}
$dataArray[$key] = intval($value);
$i ++;
}
array_unshift($dataArray, array("Terms","Visits"));
echo json_encode($php_array);
Assuming you can't change the data at its source (you say it is coming from an external API), you may have to explicitly convert the string to an integer yourself:
$dataArray[$key] = intval($value, 10);
or
$dataArray[$key] = (int)$value;
You may want to check that $value is actually a valid number before converting it - use is_numeric for that

Categories