Cakephp 3: Collections getting to middle array entities - collections

I'm trying to build a view that shows the most recent (now four but eventually five) years of data in a chart. I'm able to pull the data successfully in a variable the shows the most recent 4 years(I don't have the fifth year in the database yet). In order to break it down for the view and add some calculations on associated arrays, I have created a collection. I can get to the first and last array entity but can not figure out how to break out the middle two arrays.
public function viewAsuFiveYear()
{
$asuFiveYearEnrollments = $this->Enrollments->find('all', [
'contain' => ['Azinstitutions', 'FallFtes', 'FallHeadcounts', 'ProjectedEnrollments',
'FallHeadcounts.Locations', 'FallHeadcounts.StudentTypes', 'FallHeadcounts.ResidentStatuses', 'FallHeadcounts.Campuses',
'FallFtes.Locations', 'FallFtes.StudentTypes', 'FallFtes.ResidentStatuses', 'FallFtes.Campuses']
], ['limit' => 5])->where(['azinstitution_id' => 1])->order(['enrollment_year' => 'DESC']);
$collection = new Collection($asuFiveYearEnrollments);
$yearone = $collection->first();
$yearTwo = $collection->take(1, 1);
$yearFour = $collection->last();
$collection1HC = new Collection($yearone->fall_headcounts);
$onCampusesHc1 = $collection1HC->match(['location_id' => 1 ])->match(['campus_id' => NULL]);
$collection4HC = new Collection($yearFour->fall_headcounts);
$onCampusesHc4 = $collection4HC->match(['location_id' => 1 ])->match(['campus_id' => NULL]);
$this->set(compact('asuFiveYearEnrollments', 'azinstitutions', 'yearone', 'yearTwo', 'yearFour', 'onCampusesHc1', 'onCampusesHc4'));
}
I tried ->take (one array, second position) but it times out with that. Not sure what filter I can use to get to the 2nd or 3rd entity array.

I believe I've figured it out. May not be the best answer but it works. for the second year I skipped the 1st array and grabbed the first array in what was left.
and the same with the third year.
$yearTwo = $collection->skip(1)->first();
$yearThree = $collection->skip(2)->first();

Related

Is it possible to remove `Future` part from Stream<List<Future<String>>> to make it Stream<List<String>>?

I want to know if it is possible in Dart to convert stream of object A to another object B, when a converter only returns Future. (e.g. A -> Future<B>)
Below is an example...
Future<Car> getCar(String carId){
...
}
main(){
Stream<List<String>> carIds = listCarIds(...);
Stream<List<Car>> cars = ?? // <-- Is it possible to get this when `getCar` only returns future?
}
I could only make Stream<List<Future<Car>>> but not Stream<List<Car>>.
Based on #user2864740's recommendation, I was able to convert using below chain methods.
Stream<List<String>> idStream = ...
Stream<List<Car>> carStream = idStream
.map((ids) => ids.map((id) => getCar(id)))
.map((carFutureList) => Future.wait(carFutureList))
.asyncMap((futureCarList) => futureCarList);

How to Group By on Columns in datatable in Linq

var res3 = dtPriorityMatrix.AsEnumerable()
.GroupBy(hour => hour.Field<int>("Hour"))
.OrderBy(item => item.Key)
.Select(item => new { Hour = item.Key });
I have a data table with 5 columns and around 200+ rows of data. One has hours (0-23) and others are Priority 1, Priority 2 and so on till Priority 4. I need to extract number of items of each priority for every hour. I need help with the Linq query as it is not my strong field. Thanks
You have to group by both columns. something like this
var query = source.GroupBy(x => new { x.Column1, x.Column2 });
so your code will be
var res3 = dtPriorityMatrix.AsEnumerable()
.GroupBy(hour =>new { hour= hour.Field<int>("Hour"), priority=hour.Field<int>("Priority")} )
.Select(item => new {count=item.count(), Hour = item.Key.hour, priority = item.Key.priority});\
edit
Reply to your comment:
when you have your results in a list, you can write it in anyway that you want.
the out put of the query is a list that contains hour, priority and count.
if you want it in 3 lines of string
string hLine="";
string pLine="";
string countLine="";
foreach(var item in res3)
{
hLine+= item.hour+" ";
pLine+= item.prioriy+" ";
countLine+= item.count+" ";
}
if you want to have them in a table or anything, use the same approach for filling your tables items

server timeout on Dynamo DB query operation to get items from a table

I have an array of ids (eventids) which can be million or billion ids inside the table. I am using a for loop to go through each id and retrieve an item from a dynamo db table using the query operation in PHP. However, because the query operation goes over a large amount of info in my table, it takes too long the query operation to do its work. So, in this case I don't get any result because I get a time out. The following code tries to do this operation, which is failing for large amounts of info. I am wondering if you have any recommendation or suggestions on how to make the query operation faster and doable for large amounts of ids inside the $sfweventarrayRDS array?
for ($j = 0 ; $j < count($sfweventarrayRDS) ; $j++){
$keyconditions = array(
"eventid" => array(
"ComparisonOperator" => ComparisonOperator::EQ,
"AttributeValueList" => array(
array(Type::NUMBER => $sfweventarrayRDS[$j]["eventid"])
)
)
);
$sfweventarrayDynamo = Dynamo::getItems("eventlocation",$keyconditions,$limit);
if (count($sfweventarrayDynamo) > 0){
$timediffepoch = $sfweventarrayDynamo[0]["edatecreated"]["N"] - $sfweventarrayRDS[$j]["edatecreated"];
$timediffstandard = new DateTime("#$timediffepoch");
if ($timediffstandard->format('i') >= 5){
$starttimeepoch = $sfweventarrayRDS[$j]["edatecreated"];
$endtimeepoch = $sfweventarrayDynamo[0]["edatecreated"]["N"];
$starttimestandard = new DateTime("#$starttimeepoch");
$endtimestandard = new DateTime("#$endtimeepoch");
$each_event = array("eventid" => $sfweventarrayDynamo[0]["eventid"]["N"],
"organizationid" => $sfweventarrayRDS[$j]["organizationid"],
"userid" => $sfweventarrayDynamo[0]["userid"]["N"],
"starttime" => $starttimestandard->format('Y-m-d H:i:s'),
"endtime" => $endtimestandard->format('Y-m-d H:i:s'),
"location" => $sfweventarrayRDS[$j]["location"],
"startlatitude" => $sfweventarrayRDS[$j]["latitude"],
"startlongitude" => $sfweventarrayRDS[$j]["longitude"],
"endlatitude" => $sfweventarrayDynamo[0]["latitude"]["N"],
"endlongitude" => $sfweventarrayDynamo[0]["longitude"]["N"]);
array_push($safewalkeventsDynamo, $each_event);
}
}
}
There can be two possible solutions that can improve your query operation:
Use batch get: If you already know event IDs and want to query the db to get more information, then batch get would be ideal. You create a chunk of 100 IDs (max allowed) and call DynamoDB to get information in one go. Repeat until you get all the IDs. Here is the documentation link.
You can increase your tables' read capacity according to your needs. (This will result in paying more money for dynamoDB.)

Unexpected notice: undefined index when null

I've written a little script that is supposed to create an array that looks something like this:
array(1 => array( 'month' => 'Jan',
'salary' => '01/31/2013',
'bonus' => '02/15/2013'),
2 => array('month' => '',...));
You get the basic idea: the index in the main array are the months (numerically), each holding an array that is to be filled dynamically. The month key depends on the language the user requested, the salary and bonus are assigned the dates when the salary and or bonus was payed. So far no surprizes.
To get the basic structure of that array, I thought this would be the easiest:
$this->months = array_fill_keys(range(1,12), array( 'month' => null,
'salary' => null,
'bonus' => null));
I then fill the array, and things run smoothly all the same, right up until the point where I want to write the data to a file, which I did like so:
private function writeFile()
{
foreach($this->months as $key => $vals)
{
if ($vals['month'] === null)
{//Only filled from date x to date y, some months can be empty
continue;
}
//this seems to raise notices?
if ($vals['salary'] === null)
{
$vals['salary'] = 'Does not apply';
}
fwrite($this->file, implode(',', $vals).PHP_EOL);
}
fclose($this->file);
return $this;
}
The line where I check if the salary is null raises notices: "Warning: Undefined index salary". At the moment I've had to add this to the code:
if (!array_key_exists('salary', $vals) || $vals['salary'] === null)
{
if (!array_key_exists('bonus', $vals) || $vals['bonus'] === null)
{
break;
}
$vals['salary'] = 'Does not apply';
}
To get to the result I need. I have googled this, and stumbled across this bug report, which was last modified 4 years ago (2009-05-08), but the status is still set to "no feedback".
Has anyone else encountered a similar glitch/bug? Or am I missing something here? How can I avoid this issue without the need for all too many if's and function calls without changing my settings (E_STRICT | E_ALL, as it should be).
BTW: I'm running PHP 5.4.7, on Slackware 14. For this little application, I'm using 2 Symfony components (ClassLoader and Console), but since this is part of an object that has nothing to do with Symfony, apart from being loaded through UniversalClassLoader I don't think that's relevant.
Since the bug is said to be PDO related: yes, I am using PDO, but in another class.
I am not sure , but try to use
$this->months = array_fill(1,12, array( 'month' => null,
'salary' => null,
'bonus' => null));
After a couple of var_dumps, I found out what the cause was: The array keys were range(1,12), to determine the which month was I was processing. For that I used a DateTime object in the following fashion:
$date->modify('+ '.$diff.' days');
$key = $date->format('m');
The problem was that the format call returns a string. The goal was to list when the salary and bonus are to be paid. The bonus has to be paid each 15th, or the following Wednesday, if the 15th was a Saturday or Sunday. The salary is to be paid the last day of the month, or the last Friday.
In other words, the bonus pay date is assigned like so:
$key = $date->format('m');
$this->months[$key]['month'] = $date->format('M');
if ($date->format('d') == 15)
{
//find find week-day (15th or following Wednesday)
$this->months[--$key]['bonus'] = $date->format('m/d/Y');
$key++;
//set date to end of month
}
//check week-day, and modify date if required
$this->months[$key]['salary'] = $date->format('m/d/Y');
Because the keys of the $this->months array are numeric, but the format used for $key is a 2-digit string, with leading zeroes, I was having problems.
Each 15th of the month, the $key value is coerced to an integer (decrement/increment operators), but the month is assigned using a string.
The information I provided in my original question was insufficient, sorry for that, but I had just put in an all-nighter. The fix, in the end was pretty easy:
$key = (int) $date->format('m');//cast
I sincerely appreciate all responses, and everyone contributing to the SO community. I would've deleted this question, but if nobody objects, I think I might leave it be as a testimony to my stupidity.

Smarty Math Function Foreach Loop

I am using smarty templating engine and am encountering a math issue. I am trying to create a total amount (sum) based on amounts in the array. (Normally I would do this at the server level, but do to the way that I create the array, dont think that is possible.) I am merging two arrays into one, but each array shares an 'Amount' which I am trying to determine the 'Total Amount'
Here are the steps I am taking two arrays pushing into one array:
foreach ($data_main1 as $transaction_main1) {
$json_decoded = json_decode($transaction_main1['NewObject']);
$amount = $transaction_main1['Amount'];
$mycart1[] = array('ParentType' => $ParentType, 'Amount' => $amount);
}
$mycart2=array();
foreach ($data_main2 as $transaction_main2) {
$json_decoded = json_decode($transaction_main2['NewObject']);
$amount = $transaction_main2['Amount'];
$mycart2[] = array('ParentType' => $ParentType, 'Amount' => $amount);
}
$mycart = array_merge((array)$mycart1, (array)$mycart2);
$smarty->assign('cart', $mycart);
Here is my Smarty along with the math equation that does not show the value:
{assign var=last value=$cart[cart].Amount+1}
(I am certainly open to the idea of creating a total amount on the array_merge, just unsure how to do that, or even if it is possible)
Do you know about the {math} Smarty bult-in function?
{math equation="x + 1" x=$cart[cart].Amount}
Let me know if it works.

Resources