Count number of elements within Objects - php

I have a Submission Model and using a query, I get a list of all Submissions. Then in order to get into each submission, I use a loop
foreach ($submissions as $submission) {
}
Each submission has the following elements
[original:protected] => Array
(
[id] => 1
[sessionKey] => dfshduifhsduifhsdiu
[number] => 9
[isCompleted] => 0
[created_at] => 2017-07-29 23:14:02
[updated_at] => 2017-07-30 00:04:00
)
What I am trying to do is produce an array which outputs some details about all of the submissions. First thing I need is the total number of submissions. Next I need the number of complete (isComplete = 1) and incomplete (isComplete = 0) records. In order to achieve this, I am doing
function submissionSummary($submissions) {
$reportArray = array();
$totalCount = 0;
$incompleteCount = 0;
$completeCount = 0;
foreach ($submissions as $submission) {
$totalCount += count($submission);
$reportArray["total"] = $totalCount;
if($submission['isCompleted'] === "0") {
$incompleteCount += count($submission);
$reportArray["incomplete_count"] = $incompleteCount;
} elseif ($submission['isCompleted'] === "1") {
$completeCount += count($submission);
$reportArray["complete_count"] = $completeCount;
}
}
return $reportArray;
}
I am not sure if there is a more effecient way of doing this?
Now the part I am struggling with is the number element. This number can be anything from 1 - 9. What I am trying to do is count the number of each number. So I want to see how many submissions have a number element 1, how many have 2 etc. The only way I can think of to achieve this is through a lot of if statements, which if possible I would like to avoid.
Any advice on how I can structure this properly appreciated.
Thanks

The easy way is to drop the foreach and just do:
function submissionSummary($submissions){
$report = []; // or array() if you prefer
$report['completeCount'] = $submissions->where('isCompleted', 1)->count();
$report['inCompleteCount'] = $submissions->where('isCompleted', 0)->count();
$report['totalCount'] = $submissions->count();
return $report;
}

Related

PHP arrays - unique combinations out of 3 arrays

I'm not even sure how to approach the problem so I'm just stating the problem. Any help is highly appreciated.
There's this array ($colors) of all possible values:
$colors = array ('red','blue','green','yellow');
Then there's an array ($boxes) of all the possible values - consisting of equal number of values as $colors:
$boxes = array ('circular','squared','hexagonal','triangular');
There's this third array which defines the constraints in making the unique combination:
$possible_combos = array
(
array('circular','red','blue'),
array('squared','red','green'),
array('hexagonal','blue','yellow'),
array('triangular','red','green')
);
Question: How do I get a new array $result with key=>value combinations just that each box is assigned a unique color out of it's possible sets of colors
So a valid $result array would be:
Array ( [circular] => red
[squared] => blue
[hexagonal]=> yellow
[triangular] => green
)
NOTE: If you traverse sequentially, 'red', 'blue', 'green' might get assigned to first three 'boxes' and there might not be anything to pick for the fourth box (since 'yellow' is not allowed to be assigned to it.
I'm thinking, to process the least occurring 'colors' first but really unsure how to handle it syntactically.
Once again thanks for looking into it, in advance! Even some help with how to approach the problem would be nice.
Following code is not producing the correct output either:
foreach ($colors as $c => $color) {
foreach ($boxes as $b => $box) {
for ($i=0; $i < count($colors) ; $i++) {
if(in_array($possible_combos[$i][1],$colors) && !in_array($possible_combos[$i][1], $result))
{
$result[$box] = $possible_combos[$i][1];
unset($colors[$c]);
break;
}
else if(in_array($possible_combos[$i][2],$colors) && !in_array($possible_combos[$i][2], $result))
{
$result[$box] = $possible_combos[$i][2];
unset($colors[$c]);
break;
}
}
}
}
I'm thinking, to process the least occurring 'colors' first but really unsure how to handle it syntactically.
That's a good intuition considering the fact that you have only one box type that can share one of many colors. Because your constraining resource is color, I think it makes sense to sort your rules by them first and then you can distribute by scarcity.
https://3v4l.org/u5pBK
$colors = array ('red','blue','green','yellow');
$boxes = array ('circular','squared','hexagonal','triangular');
$possible_combos = array
(
array('circular','red','blue'),
array('squared','red','green'),
array('hexagonal','blue','yellow'),
array('triangular','red','green')
);
// collect constraints ordered by rarest
foreach ($possible_combos as $constraint) {
$box = array_shift($constraint);
foreach ($constraint as $color) {
$constraints[$color] []= $box;
}
}
// assign rarest first to last
asort($constraints);
foreach ($constraints as $color => $allowedBoxes) {
foreach ($allowedBoxes as $box) {
$key = array_search($box, $boxes);
// if we have a match, then remove it from the collection
if ($key !== false) {
$result[$box] = $color;
unset($boxes[$key]);
continue 2;
}
}
}
print_r($result);
Array
(
[hexagonal] => yellow
[circular] => blue
[squared] => green
[triangular] => red
)

PHP- Finding the Sum of values for each ID in an Associative Array

I have 2 Arrays. The First Array is a 1D Array which contains User ID's.
Something like this Array ( [0] => 1042800 [2] => 1184921 [4] => 724911 [66] => 1271106 )
I have a second Array which is an Associative Array, which contains Information for each User ID. It is something like this
Harvest_DayEntry::__set_state(array('user-id'=>1042800 'hours'=>2 ,Harvest_DayEntry::__set_state(array('user-id'=>1042800 'hours'=>4 ))
That was actually a part of the array. Now I am Interested in calculating the total hours for each User ID.
This is what I have tried.
//Add all the Hours for a Given User ID
//$output is the Array of User ID's
$resultGetEntries=$api->getProjectEntries($project_id,$range);
$dayEntries= $resultGetEntries->data;
$i=0;
$sum=$sum[20];
$sum= array_fill(0, 20, 0);
foreach ($dayEntries as $key => $value) {
if($output[i] == $value->get("user-id")) {
$sum[$i] = $sum[$i] + $value->get("hours");
}
$i++;
}
Eventually I want to get something like this
User ID Hours
1042800 15
1184921 18
724911 10
1271106 8
I am not too sure how to go about it. I can't seem to figure out how do I loop over an Associative array and calculate the sum for each user ID at the same time. I just need to know the proper logic to solve this problem.
I assume $resultGetEntries is your user ids array and $dayEntries is the Harvest_DayEntrys array.
The simplest way to combine both is iterarting over both in a double loop:
$resultGetEntries = $api->getProjectEntries($project_id,$range);
$dayEntries = $resultGetEntries->data;
$sums = array();
foreach ($resultGetEntries as $i => $userId) {
$sums[$userId] = 0;
foreach ($dayEntries as $j => $dayEntry) {
if ($dayEntry->get("user-id") == $userId) {
$sums[$userId] += $dayEntry->get("hours");
}
}
}
print_r($sums);

Array updating temporarily, but not updating permanently in PHP

Here's the code:
if($condition == 'condition1' || $condition == 'condition2')
{
$found = false;
//loop through the array of customers contracts
foreach($cust_cont as $cust)
{
//if the customer is found
if ($cust["customer"] == $customer)
{
$temp = floatval($cust["hoursThisPer"]);
$temp += $time;
$cust["hoursThisPer"] = $temp;
$found = true;
}
}
if ($found == false)
{
$cust_cont[] = array("customer" => "$customer", "hoursUsed" => $hoursUsed,
"hoursAvail" => $allowed, "hoursThisPer" => (0 + $time));
}
}
So, what I'm trying to get this to do is traverse an array. If the array does have an entry for a customer, I want to add time to that customer's used time. If there is not an entry for the customer, I want to create an entry for that customer in my array and initialize it's values.
The array's entries are getting initialized properly, but when I try to update them, something funky is happening. For example, if I have customer1 in the array and I want to add to customer1's hoursThisPer, it goes through the motions of adding to that spot. However, the next time it needs to update, customer1's hoursThisPer is set to the initial value as opposed to the updated value. I can't figure out the flaw in my logic. Help would be greatly appreciated. I have some sample output.
Customer1:0.25
time: 0.25
temp: 0.5
0.5
Customer1:0.25
time: 1.50
temp: 1.75
1.75
Customer1:0.25
time: 0.50
temp: 0.75
0.75
The format is Customer: initial time; time to add; the expected total of initial time + added time; the array's value after being "updated"; the next instance of the customer being found (and the cycle continues).
You need to fetch your array by reference, otherwise you're just updating a new variable called $cust:
if($condition == 'condition1' || $condition == 'condition2')
{
$found = false;
//loop through the array of customers contracts
foreach($cust_cont as &$cust)
{
//if the customer is found
if ($cust["customer"] == $customer)
{
$temp = floatval($cust["hoursThisPer"]);
$temp += $time;
$cust["hoursThisPer"] = $temp;
$found = true;
}
}
if ($found == false)
{
$cust_cont[] = array("customer" => "$customer", "hoursUsed" => $hoursUsed,
"hoursAvail" => $allowed, "hoursThisPer" => (0 + $time));
}
}
Here I added a & before $cust declaration in the foreach loop. With this $cust is not a new variable with the value of the current $cust_cont element but an actual reference to this element.
By default the variables created inn foreach loops ($cust in this case) are created by value rather than by reference.
You could either change it to pass by reference (by prefixing with an &, as suggested by splash58 in a comment), allowing you to alter the original array by changing the created variable:
foreach($cust_cont as &$cust)
{
//if the customer is found
if ($cust["customer"] == $customer)
{
$temp = floatval($cust["hoursThisPer"]);
$temp += $time;
$cust["hoursThisPer"] = $temp;
$found = true;
}
}
or you could also get the relevant index and edit the array directly;
foreach($cust_cont as $index => $cust)
{
//if the customer is found
if ($cust["customer"] == $customer)
{
$temp = floatval($cust["hoursThisPer"]);
$temp += $time;
$cust_cont[$index]["hoursThisPer"] = $temp;
$found = true;
}
}
Personally I find it easy to miss the "&" so prefer the second option but I'm sure that's not even close to a universal opinion.
As PHP Manual says: http://php.net/manual/en/control-structures.foreach.php
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.

Arrays inside array to hold filenames

This is for the front page of a website, which is supposed to display the newest/latest post at the very top, as you scroll down and goto the next pages, the posts get older.
There is a folder the contains lots of ini files with only numbers in the names. What i'm trying to do is load all the posts names (and only names - not their contents) into an array then sort those out to other arrays. I thought maybe using a multidimensional array would be a good idea. For example (if im understanding this right), $usePage[1][2] would have the number of the second post on page one. Is even the best way to do this?
Here is the relevant bit of code:
$ppp = 4;
$totalposts = 0;
$posts = array();
foreach (scandir($postsLoc) as $file) {
if (is_file($postsLoc . "/" . $file)) {
$totalposts++;
array_push($posts, $file);
}
}
natsort($posts);
array_values($posts);
$posts = array_reverse($posts);
print_r($posts);
$currPage = -;
$usePage = array(array());
$done = 0;
for ($i = $totalposts; $i != 0; $i--){
if ($done >= $ppp){
//Next page
$currPage++;
$done = 0;
$usePage[$currPage] = array();
}
$done++;
array_push($usePage[$currPage][$done], $i);
}
print_r($usePage);
So far, I've managed to confuse myself.
Thanks for any help in advance!
the below code results in a multi dimenstional $postsInPage array, the first dimension being the page ref, the second being the posts for that page. You should then be able to use this array pull out the relevant posts dependant on your pageId:
Array
(
[1] => Array
(
[0] => .
[1] => ..
[2] => email_20131212_2c7a6.html
[3] => email_20131212_98831.html
)
[2] => Array
(
[0] => errFile_20140110_940ad.txt
[1] => errFile_20140110_2021a.txt
[2] => errFile_20140110_2591c.txt
[3] => errFile_20140110_43280.txt
etc, etc. The code (haven't included the is_file check)
// load all the posts into an array:
$allPosts = array();
foreach (scandir("temp") as $file) {
$allPosts[] = $file;
}
//sort the array (am making an assumption that $file structure will natsort sensibly
natsort($allPosts);
$allPosts = array_values($allPosts);
//split into posts per page.
$ppp = 4;
$pageId = 1;
$totalposts = 1;
$postsInPage = array();
foreach ($allPosts as $post) {
$postsInPage[$pageId][] = $post;
if (($totalposts % $ppp) == 0) { //i.e. 4 per page
$pageId++;
}
$totalposts++;
}

Search in array query result in php/mysql

I have the mysql results ($date_options) as below
Array (
[0] => stdClass Object (
[id] => 4
[start_date] => 2010-09-29
)
[1] => stdClass Object (
[id] => 13
[start_date] => 2010-10-06
)
)
I need to be able to search in the "id" field if some value existed. I tried this and it didn't work:
array_search($event_id, $date_options, true)
$event_id is has the id value. I only want to look in id and not in start_date
How to solve this?
Thanks
Since you're already using MySQL, why don't you select only the ID you are interested in? That would be more efficient than retrieving all records and then searching in PHP.
If you still want to do it this way, you can simply iterate over the array and check manually:
foreach ($date_options as $result) {
if ($result->id == $event_id) {
// do something
}
}
Try this:
function searchEventForId($eventId, $dateOptions){
foreach($dateOptions as $event){
if($event->id === $eventId){
return $event;
}
}
return null;
}
$event = searchEventForId($event_id, $date_options);
All answers are spot-on, but for the sake of expandability, here's a function that is "re-usable" and it's going to search recursively through even deeper arrays, with the possibility of specifying both the key and its value. It's going to stop at the first match and return its value, but again, for the sake of expandability it could quite easily be modified to return an array of matched key/value pairs, in case multiple results are expected.
function search_my_array($my_key, $my_value, $array) {
foreach($array as $key => $value) {
if(!is_array($value)) {
if(($key == $my_key) && ($value == $my_value)) {
return $value;
}
} else {
if(($result = search_my_array($my_key, $my_value, $value)) !== false) {
return $result;
}
}
}
return false;
}
So in your case, you'd be using it like:
$event = search_my_array('id', $event_id, $date_options);
I'd suggest however that you go for one of the much simpler solutions posted, if you only need the search function for this particular task, but maybe somebody will find this useful at some point.
This is Tested you may try it, I have used in my one of projects
function FindData($fKey, $find_val, $res) {
$arr = $res;//json_decode($res, true);
foreach ($arr as $key => $value) {
if ($value[$fKey] == $find_val) {
return $value;
}
}
}
example:
$row = FindData('KeyName', 'Value', 'ArrayData or mySql Result Set');
It wont hit MySQL Database each time to fetch patricular data.

Categories