Using average() in 2sxc numeric field - dotnetnuke

#inherits ToSic.Sxc.Dnn.RazorComponent
#using System.Linq;
#{
var Measures = AsList(App.Data["Measures"]);
}
<p>#Measures.Where(... something ...).Select(s => s.Time).Max()</p>
<p>#Measures.Where(... something ...).Select(s => s.Time).Min()</p>
<p>#Measures.Where(... something ...).Select(s => s.Time).Average()</p>
Max and min work. Average returns:
'System.Collections.Generic.IEnumerable<dynamic>' does not contain a definition for 'Average' and the best extension method overload 'System.Linq.Queryable.Average(System.Linq.IQueryable<int>)' has some invalid arguments
Time is a numeric field.
I assume I am missing some sort of cast?

Min and Max are probably very generic, since even a string can have min/max.
Average really needs to be sure it's a number. My guess is this should fix what you're doing
<p>#Measures.Where(... something ...).Select(s => (double)s.Time).Average()</p>
This may cause trouble if s.Time is null, in which case you would want something like
<p>#Measures.Where(... something ...).Select(s => s.Time as double? ?? 0).Average()</p>
didn't try it, but it should probably work. Casting to double? means nullable-double, and then adding ?? 0 should make sure all nulls are 0.

Ended with
var GetMeasures = Measures.Where(u => u.Category.CatName == c.CatName && !u.Time.Equals(null));
var getTimes = GetMeasures.Select(s => (double)s.Time);
if (getTimes.Count() > 0) {
<p>#getTimes.Max()</p>
<p>#getTimes.Min()</p>
<p>#getTimes.Average()</tdp
}

Related

Summing the values of multiple Vectors in the session

In my gatling scenario, I need to check the session for a few entries that will be Vectors of numbers. I can get the Vectors if present, but when I attempt to add them using .sum I get a ClassCastException stating that java.lang.String can't be cast to java.lang.Integer
I've debugged by printing out the value retrieved from the session (Vector(100,200,300)), and even confirmed that the individual elements are Ints. However when I try to add any of them, either with something like values.sum or values(0)+values(1) I get the class cast exception
I'm setting values in the session with checks like
.check(jsonPath("$..payments..paymentAmount").findAll.optional.saveAs("payments"))
.check(jsonPath("$..receipts..receiptAmount").findAll.optional.saveAs("receipts"))
in my app these will always result in things like Vector(100, 200, 300) if the path was there
then later I want to sum all the values in these lists so I have the action
.exec(session => {
def addAmounts(listNames: Array[String]): Int = {
listNames.foldLeft(0)((acc, listName) => {
session(listName).validate[Seq[Int]] match {
case Success(ints) => ints.sum + acc
case Failure(error) => acc
}})
}
val transactionsTotal = addAmounts(Array("payments", "receipts"))
session.set("total",transactionsTotal)
}
As mentioned, this fails on the listName.sum + acc statement - since they're both Ints I'd expect there'd be no need to cast from a string
The Failure case where nothing was stored from the check works fine
I think this is a scala type inference issue - I got it working by manually casting to Int before doing addition

Scala: Using a value from an array to search in another array

I have two arrays:
GlobalArray:Array(Int,Array[String]) and SpecificArray:Array(Int,Int).
The first Int in both of them is a key and I would like to get the element corresponding to that key from the GlobalArray.
In pseudocode:
val v1
For each element of SpecificArray
Get the corresponding element from GlobalArray to use its Array[String]
If (sum <= 100)
for each String of the Array
update v1
// ... some calculation
sum += 1
println (v1)
I know using .map() I could go through each position of the SpecificArray, but so far I was able to do this:
SpecificArray.map{x => val in_global = GlobalArray.filter(e => (e._1 == x._1))
// I don't know how to follow
}
How about something like below, I would prefer to for comprehension code which has better readability.
var sum:Int = 0
var result:String = ""
for {
(k1,v1) <- SpecificArray //v1 is the second int from specific array
(k2,values) <- GlobalArray if k1 == k2 //values is the second array from global array
value <- values if sum < 100 //value is one value frome the values
_ = {sum+=1; result += s"(${v1}=${value})"} //Update something here with the v1 and value
} yield ()
println(result)
Note needs more optimization
Convert GlobalArray to Map for faster lookup.
val GlobalMap = GlobalArray.toMap
SpecificArray.flatMap(x => GlobalMap(x._1))
.foldLeft(0)((sum:Int, s:String) => {
if(sum<=100) {
// update v1
// some calculation
}
sum+1
})
If not all keys of SpecificArray is present in GlobalMap then use GlobalMap.getOrElse(x._1, Array())
How sum affects the logic and what exactly is v1 is not clear from your code, but it looks like you do search through GlobalArray many times. If this is so, it makes sense to convert this array into a more search-friendly data structure: Map. You can do it like this
val globalMap = GlobalArray.toMap
and then you may use to join the strings like this
println(SpecificArray.flatMap({case (k,v) => globalMap(k).map(s => (k,v,s))}).toList)
If all you need is strings you may use just
println(SpecificArray.flatMap({case (k,v) => globalMap(k)}).toList)
Note that this code assumes that for every key in the SpecificArray there will be a matching key in the GlobalArray. If this is not the case, you should use some other method to access the Map like getOrElse:
println(SpecificArray.flatMap({case (k,v) => globalMap.getOrElse(k, Array()).map(s => (k,v,s))}).toList)
Update
If sum is actually count and it works for whole "joined" data rather than for each key in the SpecificArray, you may use take instead of it. Code would go like this:
val joined = SpecificArray2.flatMap({case (k,v) => globalMap.getOrElse(k, Array()).map(s => (s,v))})
.take(100) // use take instead of sum
And then you may use joined whatever way you want. And updated demo that builds v1 as joined string of form v1 += String_of_GlobalArray + " = " + 2nd_Int_of_SpecificArray is here. The idea is to use mkString instead of explicit variable update.

Angular 2 / Typescript - how to check an array of objects to see if a property has the same value?

This question does it in Javascript, but I would have thought in Typescript I could do some kind of map/filter operation to do the same thing.
I have an array of objects called Room. Each Room has a property called Width (which is actually a string, eg '4m', '5m', '6.5m').
I need to check the entire array to see if all the widths are the same.
Based on that question I have this, but I was wondering if TypeScript has something better:
let areWidthsTheSame = true;
this.qp.rooms.forEach(function(room, index, rooms) {
if (rooms[index] != rooms[index+1]) areWidthsTheSame = false;
});
Any ideas?
FYI the linked question has a comment that links to these performance tests, which are interesting in the context of this question:
This can be done in the following way:
const widthArr = rooms.map(r => r.width);
const isSameWidth = widthArr.length === 0 ? true :
widthArr.every(val => val === widthArr[0]);
We first convert the rooms array to an array of widths and then we check if all values in widths arrays are equal.

CAKEPHP create unique code on entries in database

ok sorry, wrote too little info here and i have done some research:
The question: What is the easiest way to write a model function that creates an unique code (5 characters) for each row in a cake model/table that doesnt already have a code?
//create a unique code
//set the random id length
function generateCode()
{
while($i > 0)
{
$random_id_length = 7;
//generate a random id encrypt it and store it in $rnd_id
$rnd_id = crypt(uniqid(rand(),1));
//to remove any slashes that might have come
$rnd_id = strip_tags(stripslashes($rnd_id));
//Removing any . or / and reversing the string
$rnd_id = str_replace(".","",$rnd_id);
$rnd_id = strrev(str_replace("/","",$rnd_id));
//finally I take the first 7 characters from the $rnd_id
$rnd_id = substr($rnd_id,0,$random_id_length);
//check if the code is unique
$i = $this->checkCode($rnd_id);
}
return $rnd_id;
}
//check to see if the code isnt already in the database
function checkCode($code)
{
$conditions = array("uniqueCode" => $code));
$result = $this->Visitors->count('all', array('conditions' => $conditions));
return $result;
}
//check how many has a code
function check()
{
$conditions = array("NOT" => array ("uniqueCode" => null));
$result = $this->Visitors->count('all', array('conditions' => $conditions));
return $result;
}
function update()
{
//update until everyone has a code
while( $i > 0)
{
$this->generateCode()
// get next visitors that DONT have a code.
$conditions = array ("uniqueCode" => null));
$visitor = $this->Visitors->find('first', array('conditions' => $conditions));
$i = $this->check();
}
echo 'Done';
}
Cant make it work properly and it must be an easier way?
How about an id column? :]
If You want it to be like a hash thing, I think use this:
substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,;:!?.$/*-+&#_+;./*&?$-!,"), 0, 5);
and you shouldn't worry about checking whether it's unique. Or do it, so create a hash like that and try to find it in the table, if it's not in there - your good to go.
in your Model, you can do something like this
<?php
function beforeSave() {
if (empty($this->data[$this->alias]['id'])) {
$this->data[$this->alias]['id'] = base_convert(uniqid(), 16, 36);
}
return $this->data;
}
?>
This will generate a unique id of 10 chars. You can figure out how to create a unique id of 5 chars, maybe converting the string to a higher base, but I find it difficult because you'll have to make your own function, base_convert has a limit of 36
One thing to think about is the length of the code. A five character code, assuming you use upper and lower case characters in it, has 380,204,032 possible unique codes. If you create these codes truly randomly, you'll rather soon hit the point where you're creating duplicates. There's a 50% chance of collision after you have generated 22,959 codes.
So, since for each new code you need to check whether it already exists or not,
(BTW, a much more elegant check is this):
do {
$code = /* create code */;
} while (!$this->isUnique(array('code' => $code)));
over time you'll hit more and more already existing codes, slowing down the generation of each code, to the point where you may have to loop 100 or more times to find a unique code (99% chance of collision at only 59,177 codes).
If you're just talking about a few thousand records max, I wouldn't worry about it. If your dataset could/is supposed to grow beyond that though, you should think either about a different scheme for your codes (UUIDs come to mind), generate codes sequentially or pre-generate a list of all possible codes, shuffle it and use up codes one by one.
There are a gazillion ways to do this and all you have to do is google the appropriate words. I found it in the PHP manual, so that would be a good place to start.
To make it unique, it would be based on date and would incorporate some sort of hashing.
Do some searching, reading and learning.

Unsetting elements of a cakephp generated array

I have an array called $all_countries following this structure:
Array
(
[0] => Array
(
[countries] => Array
(
[id] => 1
[countryName] => Afghanistan
)
)
[1] => Array
(
[countries] => Array
(
[id] => 2
[countryName] => Andorra
)
)
)
I want to loop through an array called prohibited_countries and unset the entire [countries] element that has a countryName matching.
foreach($prohibited_countries as $country){
//search the $all_countries array for the prohibited country and remove it...
}
Basically I've tried using an array_search() but I can't get my head around it, and I'm pretty sure I could simplify this array beforehand using Set::extract or something?
I'd be really grateful if someone could suggest the best way of doing this, thanks.
Here's an example using array_filter:
$all_countries = ...
$prohibited_countries = array('USA', 'England'); // As an example
$new_countries = array_filter($all_countries, create_function('$record', 'global $prohibited_countries; return !in_array($record["countries"]["countryName"], $prohibited_countries);'));
$new_countries now contains the filtered array
Well first of all id e teh array in the format:
Array(
'Andorra' => 2,
'Afghanistan' => 1
);
Or if you need to have the named keys then i would do:
Array(
'Andorra' => array('countryName'=> 'Andorra', 'id'=>2),
'Afghanistan' => array('countryName'=> 'Afghanistan', 'id'=>1)
);
then i would jsut use an array_diff_keys:
// assuming the restricted and full list are in the same
// array format as outlined above:
$allowedCountries = array_diff_keys($allCountries, $restrictedCountries);
If your restricted countries are just an array of names or ids then you can use array_flip, array_keys, and/or array_fill as necessary to get the values to be the keys for the array_diff_keys operation.
You could also use array_map to do it.
Try something like this (it's probably not the most efficient way, but it should work):
for ($i = count($all_countries) - 1; $i >= 0; $i--) {
if (in_array($all_countries[$i]['countries']['countryName'], $prohibited_countries) {
unset($all_countries[$i]);
}
}
If you wanted to use the Set class included in CakePHP, you could definitely reduce the simplicity of your country array with Set::combine( array(), key, value ). This will reduce the dimensionality (however, you could do this differently as well. It looks like your country array is being created by a Cake model; you could use Model::find( 'list' ) if you don't want the multiple-dimension resultant array... but YMMV).
Anyway, to solve your core problem you should use PHP's built-in array_filter(...) function. Manual page: http://us3.php.net/manual/en/function.array-filter.php
Iterates over each value in the input
array passing them to the callback
function. If the callback function
returns true, the current value from
input is returned into the result
array. Array keys are preserved.
Basically, pass it your country array. Define a callback function that will return true if the argument passed to the callback is not on the list of banned countries.
Note: array_filter will iterate over your array, and is going to be much faster (execution time-wise) than using a for loop, as array_filter is a wrapper to an underlying C function. Most of the time in PHP, you can find a built-in to massage arrays for what you need; and it's usually a good idea to use them, just because of the speed boost.
HTH,
Travis

Resources