I am trying to get Liquid to simply round up a number. Here is my code:
{% assign loopCount = page.boxCount | plus:0 | divided_by:3 | %}
{{ loopCount | ceil }}
In this case loopCount = 4. I can confirm it is a number by adding to it and displaying the results.
{% assign loopCount = page.boxCount | plus:0 | plus:3.5 %}
{{ loopCount }}
Displays 7.5
However, when I divide by 3, which should be 1.333... my display shows 1. Liquid seems to be automatically rounding down.
What I need it to do is round up so I get 2. What code should I use to get the expected results?
Thanks
Edit: I should note I am aware of ceil, but I can't use that unless my number is actually a decimal.
When you divide by an integer, the result will be an integer. If you want to get a float, divide by a float (see "Controlling rounding" from: https://shopify.github.io/liquid/filters/divided_by/):
require 'liquid'
source = <<-SRC
{% assign loopCount = page.boxCount | divided_by:3.0 %}
loopCount = {{ loopCount }}
loopCount | ceil = {{ loopCount | ceil }}
SRC
#template = Liquid::Template.parse(source)
puts #template.render('page' => {'boxCount' => 4 })
results in:
loopCount = 1.3333333333333333
loopCount | ceil = 2
And if you do:
require 'liquid'
source = <<-SRC
{% assign loopCount = page.boxCount | divided_by:3 %}
loopCount = {{ loopCount }}
loopCount | ceil = {{ loopCount | ceil }}
SRC
#template = Liquid::Template.parse(source)
puts #template.render('page' => {'boxCount' => 4 })
you get:
loopCount = 1
loopCount | ceil = 1
Related
I have the following data set:
Word-1-random
Word-2-random
Word-3-random
Word-4-random
upto
Word-19-random
Other-Word-1-random
Other-Word-2-random
Other-Word-3-random
Other-Word-4-random
upto
Other-Word-19-random
Now i want to do a match on a group of date, digits 1 - 5, 6-10, 11-15 etc.
I thought it was the following:
match("^Word%-d[1-5]%-",string)
match("%-Word%-d[1-5]%-",string)
Acording to you example, the idea could be something like this:
<script src="https://github.com/fengari-lua/fengari-web/releases/download/v0.1.4/fengari-web.js"></script>
<script type="application/lua">
local text = [[
Word-1-random
Word-2-random
Word-3-random
Word-4-random
upto
Word-19-random
Other-Word-1-random
Other-Word-2-random
Other-Word-3-random
Other-Word-4-random
Other-Word-5-random
Other-Word-6-random
Other-Word-7-random
Other-Word-8-random
Other-Word-9-random
Other-Word-10-random
Other-Word-11-random
]]
local s1,s2
local grp,cnt = 0,0
text:gsub('(%S+%-)(%d+)(%-%S+)', function(p1,n,p2)
if s1 ~= p1 or s2 ~= p2 or cnt == 5 then
print('Group'..grp)
s1,s2 = p1,p2
cnt = 0
grp = grp + 1
end
print(p1..n..p2)
cnt = cnt + 1
end)
</script>
What is the purpose of declaring a variable without assigning a value to it? For example, I'm looking at the following code in a Text/XML transformation:
{%
str1;
bool1;
bool2 = false;
if (str1 != "something specific" && str1 != "") {
bool1 = false;
bool2 = true;
}
str1 = SomeFieldFromDataSource;
return "";
#%}
{% if (bool1 != false) { return "<div>"; } #%}
{% if (bool2) { return "</div><div>"; } #%}
<div>Some content...</div>
What are the first two variable declarations doing? Are they just setting those variables to some default value? Without declaring a type somehow, how would Kentico know what value to use (unless it uses a single default value for everything)? Or, are the first two declarations unnecessary?
I've searched the internet, but I'm not seeing much out there on variable declaration, other than it shouldn't be necessary unless you're assigning a value. However, I'm reluctant to start deleting portions of code since I'm pretty new to Kentico and transformation syntax.
EDIT
To enhance my understanding of unassigned variables, I performed the following test in a transformation, with the result of each conditional expression shown in the comments to the right.
{% b; s; %} <!-- Evaluation of the following expressions is the same with or without this line. -->
{% if (b == true) { return "<div>b is true</div>" } #%} <!-- false -->
{% if (b == false) { return "<div>b is false</div>" } #%} <!-- false -->
{% if (b == null) { return "<div>b is null</div>" } #%} <!-- true -->
{% if (b != true) { return "<div>b is not true</div>" } #%} <!-- true -->
{% if (b != false) { return "<div>b is not false</div>" } #%} <!-- true -->
{% if (b != null) { return "<div>b is not null</div>" } #%} <!-- false -->
{% if (s == "") { return "<div>s is empty string</div>" } #%} <!-- true -->
{% if (s == null) { return "<div>s is null</div>" } #%} <!-- true -->
{% if (s != "") { return "<div>s is not empty string</div>" } #%} <!-- false -->
{% if (s != null) { return "<div>s is not null</div>" } #%} <!-- false -->
To summarize, an unassigned variable == null, != true, != false, == "". The only one of these that may be surprising is the last one, == "". However, the documentation does state such:
Empty strings are equal to null
Generally speaking, it's safe to omit the declarations. I think the author of the code was just afraid that initializing the variables in the scope of the condition wouldn't set them globally if they weren't declared first. That's not the case.
But there's something else in the code that caught my attention. It's the return "" which may indicate this piece of code is doing some preliminary calculations whose output may be used later in the code. Don't forget it's possible to separate macro blocks like this:
// returns 2
{% return x + 2; %}
{% x = 1; %}
// returns 3
{% return x + 2; %}
Or like it's described in the documentation:
// Displays a message including the current date if the year is 2014 or more
{% date = CurrentDateTime; if (date.Year > 2013) { %}
The current date is: {% date %}. The registration period has ended.
{% } %}
So I would definitely look for any further usage of all the variables in the mentioned code.
There is no real purpose aside from inheriting the datatype of the data assigned to it. Very similar to how JavaScript works. If you declare a variable without a value, it assumes an object. If you assign a string, it will be a string. If you assign an integer it assumes an integer. So with this case, maybe the object could be an integer or a string. Either way a value should be given when it's declared just for good coding and reading ease.
If this is code in production, I'd be sure to optimize it quite a bit. But not knowing the full context of the code or if there is other code in that transformation, I'd have a hard time providing a valid example.
Update
Based on your updated code, it appears the code will only output <div>Some content...</div>
Since this code is executed each time a new item is rendered, it will not keep "global" values in place like JS might do. You will have to assign the values to str1 and str2 each time and then perform some logical checking.
In Kentico's K#, all items are stored as an "object" more or less, not strongly typed, and then i believe it takes care of how it handles it through getting that object's type.
Where is this same code from? It may be just showing an example of how to do stuff. You should be fine removing what you don't need and writing your own.
I have a categorized view, the first column is categorized and ascending.The last column calculates the total. Imagine the view name is called view1 and it looks like the following:
1st column(categorized) | 2nd column | 3rd column (total)
Australia | | 2
| Alex | 1
| Bill | 1
Brazil | | 3
| Alan | 1
| Alice | 1
| Tom | 1
Chile | | 1
| John | 1
Denmark | | 2
| Susan | 1
| Tim | 1
| | 8
I would like to retrieve the total of each categorized column, for example, the total for Australia is 2, the total for Brazil is 3. I browse on the internet and write some code but the result is not success.
Here is my first attempt: I intend to use #DbLookup, for loop and #Count.
var value = sessionScope.Value;
var lookupValue = (#DbLookup(#DbName(),"view1",value,1));
for(var a = 0; a < lookupValue.length; a++)
{
//try to display the lookupValue and the relevant total
writer.write("<tr><td>"+lookupValue[a]+"<td> "+ #Count(lookupValue[a]) + "</td></tr>");
}
When I run the code, I get the following result:
Australia 1
Australia 1
Brazil 1
Brazil 1
Brazil 1
Chile 1
Denmark 1
Denmark 1
After the first attempt, I start the second attempt: (please note, most of the code in this part I get from the internet and I just modify a little bit to suit my case)
var myView:NotesView = database.getView('view1');
var vec:NotesViewEntryCollection = myView.getAllEntries();
var viewEnt:NotesViewEntry = vec.getFirstEntry();
writer.write("<table>");
while (viewEnt != null)
{
// try to retrieve the total in the 3rd column
writer.write("<tr><td> "+ 'viewEnt.getColumnValues()[2]' +"</td></tr>");
var tmp = vec.getNextEntry(viewEnt);
viewEnt.recycle();
viewEnt = tmp;
}
writer.write("</table>");
writer.endDocument();
I run the code and the result is empty. I do not get any total of the categorized column.
I review the code from attempt 1 and attempt 2, I don't understand why I cannot get the total.
I search on the internet again and I found this similar post: Getting a summary count in a view export?
I try to apply the solution in the application:(please note, most of the code in this part I get from that post and I just add the view name in the function)
function getCategoryData(viewName, dataColumn, getChildren) {
var v = database.getView(view1); // change viewName to view1
var nav = v.createViewNav();
var ve = nav.getFirst();
var isFirst = true;
var result = "[";
while (ve) {
if (!ve.isTotal()) {
var curData = ve.getColumnValues();
if (!isFirst) {
result += ",";
}
result += "{label : \"";
result += curData[0];
result += "\", value : ";
result += curData[dataColumn];
/* for 2 level categories we fetch additional data */
if (getChildren) {
var childve = nav.getChild();
var firstChild = true;
result += ", children : [";
while (childve) {
var childData = childve.getColumnValues();
if (!firstChild) {
result += ",";
}
result += "{label : \"";
result += childData[1];
result += "\", value : ";
result += childData[dataColumn];
result += "}";
firstChild = false;
childve = nav.getNextSibling(childve);
}
result += "]"
}
result += "}";
isFirst = false;
}
ve = nav.getNextSibling(ve);
}
result += "]";
return result;
}
I run the code and I get the result like this:
[{label : "Australia", value : undefined},{label : "Brazil", value : undefined},{label : "Chile", value : undefined},{label : "Denmark", value : undefined}]
After the third attempt, I think the reason that I cannot get the total is I misunderstand the concept about how to get the total in the view.
In fact, what I would like to do is get the total of each categorized column in view1. Therefore, imagine the result will look like this:
Australia 2
Brazil 3
Chile 1
Denmark 2
Actually, I think the first attempt is very close to the result. I feel I missed something in the code (perhaps I guess in the for loop part).
How can I get the total of each categorized column in view?
Grateful for your advice on this issue please. Thank you very much.
You are on the right track with your third attempt. You definitely want to use NotesViewNavigator.
Here is a working example based on your requirements:
/*
* #param viewName Name of the view to navigate
* #param labelColumn Number of the column in the view containing the label
* Note: column count start at 0
* #param dataColumn Number of the column in the view containing
* totals. Note: column count starts at 0
* #return String representing a javascript array of objects containing label and value
*/
function getCategoryData(viewName, labelColumn, dataColumn) {
var v:NotesView = database.getView(viewName);
var nav:NotesViewNavigator = v.createViewNav();
var ve:NotesViewEntry = nav.getFirst(); // first category
var isFirst = true;
var result = "[";
while (ve) {
var curData = ve.getColumnValues();
if (curData[labelColumn] != "") { // skip the total at the bottom of the totals column
if (!isFirst) {
result += ",";
}
result += "{label : \"";
result += curData[labelColumn];
result += "\", value : ";
result += curData[dataColumn];
result += "}";
}
isFirst = false;
var tmpentry:NotesViewEntry = nav.getNextCategory();
ve.recycle();
ve = tmpentry;
}
result += "]";
nav.recycle();
v.recycle();
return result;
}
Based on the description of your view and assuming the name of your view is "countries" you would call this function like this:
getCategoryData("countries", 0, 2);
Note: I did not test this function with multiple categorized columns.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a file on linux server that has data like :
a 22
a 10
a 17
a 51
a 33
b 51
b 47
c 33
I want a shell script or linux commands to find min, avg, 90%, max and count for each value in column 1.
Example:
for a min = 10, avg = 26, 90% = 33, max = 51, and count = 5.
Here a version with even the 90% percentile using gawk.
The definition of percentile is that one given by
Wikipedia and called Nearest rank.
The function round can be found here.
#!/bin/bash
gawk '
function round(x, ival, aval, fraction)
{
ival = int(x) # integer part, int() truncates
# see if fractional part
if (ival == x) # no fraction
return ival # ensure no decimals
if (x < 0) {
aval = -x # absolute value
ival = int(aval)
fraction = aval - ival
if (fraction >= .5)
return int(x) - 1 # -2.5 --> -3
else
return int(x) # -2.3 --> -2
} else {
fraction = x - ival
if (fraction >= .5)
return ival + 1
else
return ival
}
}
# the following block processes all the lines
# and populates counters and values
{
if($1 in counters) {
counters[$1]++;
} else {
counters[$1] = 1;
}
i = counters[$1];
values[$1, i] = $2;
} END {
for (c in counters) {
delete tmp;
min = values[c, 1];
max = values[c, 1];
sum = values[c, 1];
tmp[1] = values[c, 1];
for (i = 2; i <= counters[c]; i++) {
if (values[c, i] < min) min = values[c, i];
if (values[c, i] > max) max = values[c, i];
sum += values[c, i];
tmp[i] = values[c, i];
}
# The following 3 lines compute the percentile.
n = asort(tmp, tmp_sorted);
idx = round(0.9 * n + 0.5); # Nearest rank definition
percentile = tmp_sorted[idx];
# Output of the statistics for this group.
printf "for %s min = %d, avg = %f, 90 = %d,max = %d, count = %d\n", c, min, (sum / counters[c]), percentile, max, counters[c];
}
}'
To run execute:
./stats.sh < input.txt
I am assuming that the above script is named stats.sh and your input is saved in input.txt.
The output is:
for a min = 10, avg = 26.600000, 90 = 51,max = 51, count = 5
for b min = 47, avg = 49.000000, 90 = 51,max = 51, count = 2
for c min = 33, avg = 33.000000, 90 = 33,max = 33, count = 1
Here the explanation:
counters is an associative array, the key is the value in column 1
and the value is the number of values found in the input for each
value in column 1.
values is a two dimensional (value_in_column_one, counter_per_value)
array that keeps all the values grouped by value in column one.
At the end of the script the outermost loop goes trough all the values
found in column 1. The innermost for loop analyses all the values belonging
to a particular value in column 1 and it computes all the statics.
For lines starting with a, here's an awk script.
$ echo 'a 22
a 10
a 17
a 51
a 33
b 51
b 47
c 33' | awk 'BEGIN{n=0;s=0;};/^a/{n=n+1;s=s+$2;};END{print n;print s;print s/n;}'
5
133
26.6
Using awk:
awk 'NR==1{min=$1} {sum+=$2; if(min>=$2) min=$2; if(max<$2) max=$2}
END{printf("max=%d,min=%d,count=%d,avg=%.2f\n", max, min, NR, (sum/NR))}' file
max=51,min=10,count=8,avg=33.00
EDIT:
awk '$1 != v {
if (NR>1)
printf("For %s max=%d,min=%d,count=%d,avg=%.2f\n", v, max, min, k, (sum/k));
v=$1;
min=$2;
k=sum=max=0
}
{
k++;
sum+=$2;
if (min > $2)
min=$2;
if (max < $2)
max=$2
}
END {
printf("For %s max=%d,min=%d,count=%d,avg=%.2f\n", v, max, min, k, (sum/k))
}' < <(sort -n -k1,2 f)
OUTPUT:
For a max=51,min=10,count=5,avg=26.60
For b max=51,min=47,count=2,avg=49.00
For c max=33,min=33,count=1,avg=33.00
I am reading about KMP for string matching.
It needs a preprocessing of the pattern by building a prefix table.
For example for the string ababaca the prefix table is: P = [0, 0, 1, 2, 3, 0, 1]
But I am not clear on what does the numbers show. I read that it helps to find matches of the pattern when it shifts but I can not connect this info with the numbers in the table.
Every number belongs to corresponding prefix ("a", "ab", "aba", ...) and for each prefix it represents length of longest suffix of this string that matches prefix. We do not count whole string as suffix or prefix here, it is called self-suffix and self-prefix (at least in Russian, not sure about English terms).
So we have string "ababaca". Let's look at it. KMP computes Prefix Function for every non-empty prefix. Let's define s[i] as the string, p[i] as the Prefix function. prefix and suffix may overlap.
+---+----------+-------+------------------------+
| i | s[0:i] | p[i] | Matching Prefix/Suffix |
+---+----------+-------+------------------------+
| 0 | a | 0 | |
| 1 | ab | 0 | |
| 2 | aba | 1 | a |
| 3 | abab | 2 | ab |
| 4 | ababa | 3 | aba |
| 5 | ababac | 0 | |
| 6 | ababaca | 1 | a |
| | | | |
+---+----------+-------+------------------------+
Simple C++ code that computes Prefix function of string S:
vector<int> prefixFunction(string s) {
vector<int> p(s.size());
int j = 0;
for (int i = 1; i < (int)s.size(); i++) {
while (j > 0 && s[j] != s[i])
j = p[j-1];
if (s[j] == s[i])
j++;
p[i] = j;
}
return p;
}
This code may not be the shortest, but easy to understand flow of code.
Simple Java Code for calculating prefix-Array-
String pattern = "ababaca";
int i = 1, j = 0;
int[] prefixArray = new int[pattern.length];
while (i < pattern.length) {
while (pattern.charAt(i) != pattern.charAt(j) && j > 0) {
j = prefixArray[j - 1];
}
if (pattern.charAt(i) == pattern.charAt(j)) {
prefixArray[i] = j + 1;
i++;
j++;
} else {
prefixArray[i] = j;
i++;
}
}
for (int k = 0; k < prefixArray.length; ++k) {
System.out.println(prefixArray[k]);
}
It produces the required output-
0
0
1
2
3
0
1
Python Implementation
p='ababaca'
l1 = len(p)
j = 0
i = 1
prefix = [0]
while len(prefix) < l1:
if p[j] == p[i]:
prefix.append(j+1)
i += 1
j += 1
else:
if j == 0:
prefix.append(0)
i += 1
if j != 0:
j = prefix[j-1]
print prefix
I have tried my hands using the Javascript, Open for suggestions.
const prefixArray = function (p) {
let aux = Array(p.length).fill(0);
// For index 0 the matched index will always be 0, so we will we start from 1
let i = 1;
let m = 0; // mismatched index will be from 0th
// run the loop on pattern length
while ( i < p.length) {
// 3 Cases here
// First when we have a match of prefix and suffix of pattern
if(p.charAt(i) === p.charAt(m)) {
// increment m
m++;
// update aux index
aux[i] = m;
// update the index.
i++;
}
// Now if there is no match and m !=0 means some match happened previously
// then we need to move back M to that index
else if(p.charAt(i) !== p.charAt(m) && m !== 0) {
m = aux[m-1];
// we dont want to increment I as we want to start comparing this suffix with previous matched
} else {
// if none of the above conditions then
// just update the current index in aux array to 0
aux[i] = 0; // no match
i++; // shift to the next char
}
}
return aux;
}
No offset version
This is based on the idea of what I call todo indexing:
int confix[1000000];
void build_confix(char *pattern) {
// build len %
int len_pat = strlen(pattern);
// i, j using todo-indexing.
int j, i;
confix[j = 1] = i = 0;
while (j < strlen(pattern)) {
whlie (i && pattern[j] != pattern[i])
// length -> length mapping, no offset
i = confix[i];
confix[++j] = pattern[j] == pattern[i]?
++i:
0;
}
}
Then you can use this confix[] table to find needles in the middle(test)
int kmp_find_first(char *test, char *needle) {
int j = 0, i = 0;
while (j < strlen(test)) {
while (i && test[j] != needle[i])
i = confix[i];
++j; test[j] == needle[i]?
++i:
0;
if (i == strlen(needle))
return j - strlen(needle);
}
return -1;
}