How to make a sum of array values - php

I have an array and I iterate through its first 7 values with this function:
function clicksLast7Days($data)
{
$path = $data->data->data->clicks;
$num_loops = 0;
foreach ($path as $key => $item){
$num_loops++;
if($num_loops > 7) break;
if ($key >= 0) {
$array[] = $item->clicks;
}
}
return json_encode($array);
}
The array's structure (if it helps) is:
["data"]=>
object(stdClass)#212 (3) {
["status_code"]=>
int(200)
["data"]=>
object(stdClass)#211 (3) {
["days"]=>
int(30)
["total_clicks"]=>
int(6)
["clicks"]=>
array(30) {
[0]=>
object(stdClass)#215 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466395200)
}
[1]=>
object(stdClass)#216 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466308800)
}
[2]=>
object(stdClass)#217 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466222400)
}
[3]=>
object(stdClass)#218 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466136000)
}
[4]=>
object(stdClass)#219 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466049600)
}
[5]=>
object(stdClass)#220 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1465963200)
}
[6]=>
object(stdClass)#221 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1465876800)
}
[7]=>
object(stdClass)#222 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1465790400)
}
The problem is that by using my function I get an array of elements:
[0,0,0,0,0,0,0]. But what I want is to obtain their sum (which in this case is 0), and not an array, just a number.

$clicksArray = $data->data->data->clicks;
$sum = array_sum(
array_map(
$clicksArray,
function($clickElement) {
return $clickElement->clicks;
}
)
);
What does this mean ?
array_sum will sum all values of a certain array. More information here
array_map will return all elements of an array, after applying a function (so, basically here, we are returning only clicks attribute

Related

Output and use array elements from a REST Api call in php

I am calling a REST Api to get data using curl in php. It gives me the list of data/contents in the api in Array php format.
I was able to get single element value using $resultArray[0]['nid'][0]['value'];. But my goal is to get elements in all contents in the api.
Say I want to get the following elements in the nested arrays.
$resultArray[0]['nid'][0]['value'];
$resultArray[0]['vid'][0]['value'];
$resultArray[0]['cid'][0]['value'];
And use these values in a loop too.
I am trying to search how I can do it loop, and if anyone can provide sample code, that would be appreciated.
Update:
This is the sample result of var_dump:
array(1) {
[0]=>
array(38) {
["nid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(1)
}
}
["vid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(2)
}
}
["cid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(3)
}
}
["field"]=>
array(1) {
[0]=>
array(4) {
["target_id"]=>
int(4)
}
}
}
[1]=>
array(38) {
["nid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(11)
}
}
["vid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(22)
}
}
["cid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(33)
}
}
["field"]=>
array(1) {
[0]=>
array(4) {
["target_id"]=>
int(44)
}
}
}
[2]=>
array(38) {
["nid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(111)
}
}
["vid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(222)
}
}
["cid"]=>
array(1) {
[0]=>
array(1) {
["value"]=>
int(333)
}
}
["field"]=>
array(1) {
[0]=>
array(4) {
["target_id"]=>
int(444)
}
}
}
}
And I want to use these elements values in a loop.
Say my expected result is.
Test1 = "1", "2", "3"
Test2 = "11", "22", "33"
Test3 = "111", "222", "333"
These equivalent numbers should be comming from the element nid, vid, cid.
I dont just want to assign/echo these values in the result as I have array[100s] in one api call.
Since your array is a multidimensional array, you need to have nested foreach loops:
$test = 1;
foreach ($resultArray as $items) {
// Echo the current test number
echo "Test{$test} = ";
$values = [];
foreach ($items as $item) {
// Get the correct value.
if (array_key_exists('value', $item[0])) {
$values[] = $item[0]['value'];
continue;
}
if (array_key_exists('target_id', $item[0])) {
$values[] = $item[0]['target_id'];
continue;
}
}
echo '"' . implode('", "', $values) . '"' . "\n";
$test++;
}
Demo: https://3v4l.org/fnHlV

How to make the number from an array/ json_string negative

So I have an array stored in a variable called $data that looks like this:
["data"]=>
["rows"]=>
array(30) {
[0]=>
array(3) {
[0]=>
string(10) "2016-08-15"
[1]=>
int(0)
[2]=>
int(0)
}
[1]=>
array(3) {
[0]=>
string(10) "2016-08-16"
[1]=>
int(0)
[2]=>
int(0)
}
[2]=>
array(3) {
[0]=>
string(10) "2016-08-17"
[1]=>
int(0)
[2]=>
int(0)
}
[3]=>
array(3) {
[0]=>
string(10) "2016-08-18"
[1]=>
int(0)
[2]=>
int(0)
}
By using the following function I take the values from the array:
$subscribersGained = [];
foreach ($data->data->rows as $obj) {
if (isset($obj[1])) {
// add the element to the beginning of the array
array_unshift($subscribersGained, $obj[1]);
}
if(count($subscribersGained) >= 30) {
break;
}
}
$gained = array_map( create_function('$value', 'return (int)$value;'),
$subscribersGained);
echo json_encode($gained);
And store them into a json_string that looks like this:
[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
What I need to do is that I have to make the non 0 number be negative. So in this case I want to have -1 not 1. Any ideas how to make that happen? Thank you for your time!
Well, the most primitive way to do it that I figure out it is:
foreach($array as $key => $number) {
$array[$key] = 0 - $number;
}
$gained = array(0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
$gained = array_map(function($el) { return 0-$el; }, $gained);
print_r($gained);
//from #Dmytrechko`s code

Cut array by sub array key value

I got this array
array(5) {
[0]=>
array(5) {
["id"]=>
int(1411667077)
["nachricht"]=>
string(13) "iiiiiiiiiiiii"
["user"]=>
string(15) "334607943355808"
["datum"]=>
string(16) "25.09.2014 19:44"
["deleted"]=>
string(0) ""
}
[1]=>
array(5) {
["id"]=>
int(1411701734)
["nachricht"]=>
string(2) "dd"
["user"]=>
string(15) "334607943355808"
["datum"]=>
string(16) "26.09.2014 05:22"
["deleted"]=>
string(0) ""
}
[2]=>
array(5) {
["id"]=>
int(1411701737)
["nachricht"]=>
string(6) "swfsfs"
["user"]=>
string(15) "334607943355808"
["datum"]=>
string(16) "26.09.2014 05:22"
["deleted"]=>
string(0) ""
}
[3]=>
array(5) {
["id"]=>
int(1411701739)
["nachricht"]=>
string(7) "egwegeg"
["user"]=>
string(15) "334607943355808"
["datum"]=>
string(16) "26.09.2014 05:22"
["deleted"]=>
string(0) ""
}
[4]=>
array(5) {
["id"]=>
int(1411742201)
["nachricht"]=>
string(3) "sss"
["user"]=>
string(15) "334607943355808"
["datum"]=>
string(16) "26.09.2014 16:36"
["deleted"]=>
string(0) ""
}
}
I want to cut the where the id is 1411701737 so I tryed:
foreach($array as $arr => $sub_arr)
{
if $sub_arr['id'] == 1411701737
{
break;
}
}
I know I need to create a whole new array in the foreach, but isn't there maybe a build in function?
$arr_new = array(); //Define a new array
foreach($arr_old as $a) { //Loop through the old one
if($a['id'] === 1411701737) break; //If the value of id matches, leave the foreach loop
$arr_new[] = $a; //Else, copy this array to the new array
}
print_r($arr_new); //Print the new array
$new = array();
foreach($array as $k) {
if($k['id'] == 1411701737) break;
array_push($new, $k);
}
var_dump($new);
The answer by Mooseman is likely a faster way to do this since it does not rely on a PHP function call to place the array into the new array. However unless you are doing this on a set of arrays that is in the 100k+ it really won't matter.

Foreach array organization/iteration

I have this array that I've tried iterating over and creating a new array:
array(233) {
[0]=>
array(2) {
["subject_id"]=>
int(138)
["relatedsubject_id"]=>
int(127)
}
[1]=>
array(2) {
["subject_id"]=>
int(138)
["relatedsubject_id"]=>
int(47)
}
[2]=>
array(2) {
["subject_id"]=>
int(138)
["relatedsubject_id"]=>
int(13)
}
[3]=>
array(2) {
["subject_id"]=>
int(138)
["relatedsubject_id"]=>
int(56)
}
[4]=>
array(2) {
["subject_id"]=>
int(154)
["relatedsubject_id"]=>
int(77)
}
[5]=>
array(2) {
["subject_id"]=>
int(154)
["relatedsubject_id"]=>
int(69)
}
[6]=>
array(2) {
["subject_id"]=>
int(154)
["relatedsubject_id"]=>
int(70)
}
[7]=>
array(2) {
["subject_id"]=>
int(154)
["relatedsubject_id"]=>
int(75)
I cut it short so it's not too obnoxious. This is the code I'm using now:
$subject_id = array();
foreach ($results as $mainKey => $subArrays) {
if(!isset($subject_id[$results[$mainKey]["subject_id"]])) {
$subject_id[$results[$mainKey]["subject_id"]] = array();
array_push($subject_id[$results[$mainKey]["subject_id"]], $results[$mainKey]["relatedsubject_id"]);
// $subject_id[$results[$mainKey]["subject_id"]][] = $results[$mainKey]["relatedsubject_id"];
}
}
var_dump($subject_id);
My results look like this:
array(111) {
[138]=>
array(1) {
[0]=>
int(127)
}
[154]=>
array(1) {
[0]=>
int(77)
}
Any ideas on why I'm only getting 1 value and how to modify to get each "relatedsubject_id" to fall in line with the corresponding "subject_id"? Thank you.
Edit
Expected Result:
array {
[138]=>
array(1) {
[0]=>
int(127)
[1]=>
int(47)
[2]=>
int(13)
[3]=>
int(56)
}
[154]=>
array(1) {
[0]=>
int(77)
[1]=>
int(69)
[2]=>
int(70)
[3]=>
int(75)
}
It seems you are trying to consolidate your subject ids and relatedsubject_ids. If thats the case, this may work for you.
$subject_id = array();
foreach ($results as $mainKey => $subArrays) {
if(!isset($subject_id[$results[$mainKey]['subject_id']])) {
$subject_id[$results[$mainKey]['subject_id']] = array('subject_id' => $results[$mainKey]['subject_id'], 'relatedsubject_id' => array());
}
$subject_id[$results[$mainKey]['subject_id']]['relatedsubject_id'][] = $results[$mainKey]["relatedsubject_id"];
}
Changed to your EDIT
$subject_id = array();
foreach ($results as $mainKey => $subArrays) {
if(!isset($subject_id[$results[$mainKey]['subject_id']])) {
$subject_id[$results[$mainKey]['subject_id']] = array();
}
$subject_id[$results[$mainKey]['subject_id']][] = $results[$mainKey]["relatedsubject_id"];
}
The reason why you were only getting one result is you had all your code in the if(!isset()) function. That should only not be set once. If that makes sense.

Recursive traversal of object

I'm having trouble writing a recursive function to traverse this hierarchical structure
object(stdClass)#290 (6) {
["category_id"]=>
int(1)
["parent_id"]=>
int(0)
["name"]=>
string(4) "Root"
["position"]=>
int(0)
["level"]=>
int(0)
["children"]=>
array(2) {
[0]=>
object(stdClass)#571 (7) {
["category_id"]=>
int(2)
["parent_id"]=>
int(1)
["name"]=>
string(18) "Root MySite.com"
["is_active"]=>
int(0)
["position"]=>
int(0)
["level"]=>
int(1)
["children"]=>
array(11) {
[0]=>
object(stdClass)#570 (7) {
["category_id"]=>
int(15)
["parent_id"]=>
int(2)
["name"]=>
string(9) "Widgets"
["is_active"]=>
int(1)
["position"]=>
int(68)
["level"]=>
int(2)
["children"]=>
array(19) {
[0]=>
object(stdClass)#566 (7) {
["category_id"]=>
int(24)
["parent_id"]=>
int(15)
["name"]=>
string(16) "Blue widgets"
["is_active"]=>
int(1)
["position"]=>
int(68)
["level"]=>
int(3)
["children"]=>
array(0) {
}
}
<snip....>
As you can see this nested set can go on forever.. .
What I want to return is something like this
$categories("Root" => array("Root MySite.com" => array("Widgets" => array("Blue Widgets",...))))
[EDIT] : pasting my starting point for my recursive function that will simply "flatten out" an arry or object. I would think i could modify this to make get the data structure I'm looking for but haven't been able to get it quite right.
function array_flatten($array, $return)
{
// `foreach` can also iterate through object properties like this
foreach($array as $key => $value)
{
if(is_object($value))
{
// cast objects as an array
$value = (array) $value;
}
if(is_array($value))
{
$return = array_flatten($value,$return);
}
else
{
if($value)
{
$return[] = $value;
}
}
}
return $return;
}
The question is I can't quite figure out to build the structure I'm looking for recursively, or maybe there is a more elegant php way to do this?
Try this
function run($o) {
$return = array();
foreach ($o->children as $child) {
$return[$child->name] = run($child);
}
return empty($return) ? null : $return;
}
I don't have time to write a working answer, but here's some pseudo code to do it (half PHP, half JS)
This would create a flattened version of the tree by removing the children property of each element in your list.
$flattened = array();
function addElement(&$flattened, $list) {
for ($element in $list) {
$children = $element->children;
delete $element->children;
$flattened[] = $element;
if ($children) {
addElements($flattened, $children)
}
}
}
addElements($flattened, $treeHierarchy);
deep_order object or assoc_array
namespace a_nsp
class object_utils{
static function deep_order($IN, $desc = NULL) { // object or assoc_array
$O = new \stdClass;
$I = (array) $IN;
$keys = array_keys($I);
$desc ? rsort($keys) : asort($keys);
foreach ($keys as $k) {
$v = $I[$k];
//$v = json_decode($I[$k],1) ?: $I[$k]; // force conversion of json_string
if (is_array($v) || is_object($v)) {
$O->$k = self::deep_order($v, $desc);
}
else {
$O->$k=$v;
}
}
return $O; // object
}
}
use like
$ordered_obj = \a_nsp\object_utils::deep_order($orig_obj)

Categories