If statements and extracting values - regex

I have a result set that looks like
{add=[44961373 (1645499799657512961), 44961374 (1645499799658561538), 44962094 (1645499799659610114), 44962095 (1645499799659610117), 44962096 (1645499799660658689), 44962097 (1645499799660658691), 44962098 (1645499799661707264), 44962099 (1645499799661707267), 44962100 (1645499799662755840), 44962101 (1645499799662755843), ... (592 adds)]}
If the add=[ array has more than 10 elements in it. Then it will put (x adds) at the end of the statement to show how many actual adds there were. IF it has less than 10, then it wont put the (x adds) statement. I am wanting timechart and also single value these outputs to a dashboard(separate modules).
I can get one or the other but I would like to use from logic to figure out which one to report.
index="index" host="host*" path=/update | eval count=mvcount(add) | stats count
will get the count of the array
index="index" host="host*" path=/update | stats sum(Adds)
will get the value of the (x adds). Adds is a 'extracted field'.
How do I get either or? If add array >10, use sum(Adds), in the same breath.

index="index" host="host*" path=/update | eval count=mvcount(add)
| eval first_ten="{add=[".mvjoin(mvindex(add,0,9), ",")." (" (count-10)." adds)}"
| eval msg=if(count<10,_raw,first_ten)
You can do something like this. Get the count of adds, create a new string with the first 10 elements only, with the count-10 adds message at the end. Then, depending on the actual count, either use the original (_raw), or the new message.

Related

TACL How to use multiple Arguments

I was wondering if we have any TACL experts out there can can help me answer probably a very basic question.
How do you inject multiple arguments into you routine.
This is what I have currently so far
[#CASE [#ARGUMENT / VALUE job_id/number /minimum [min_job], maximum [max_job]/
otherwise]
|1|#output Job Number = [job_id]
|otherwise|
#output Bad number - Must be a number between [min_job] & [max_job]
#return
]
I have been told you need to use a second #ARGUMENT statement to get it to work but I have had no such luck getting it to work. And the PDF guides don't help to much.
Any ideas/answers would be great
Thanks.
The #CASE statement isn't required if your arguments are positional and of one type (i.e. you know what you are getting and in what order). In that case you can just use a sequence of #ARGUMENT statements to get the arguments.
In your example #ARGUMENT accepts either a number in a range or anything else - the OTHERWISE bit. The #CASE statement then tells you which of those two you got, 1 or 2.
#ARGUMENT can do data validation for you (you may recognize the output from some of the TACL routines that come with the operating system).
So you can write something like this:
SINK [#ARGUMENT / VALUE job_id/number /minimum [min_job], maximum [max_job]/]
The SINK just tosses away the expansion of the #ARGUMENT, you don't need it since you only accept a number and fail otherwise.
I figured out a way but idk if it is the best way to do it.
It seems that for one an Argument statement needs to always be in a #CASE statement so all I basically did was mirror the above and just altered it for text rather than use integer.
If you know of any other/better ways let me know :)
It find it best to use CASE when you have multiple types of argument
input to process. Kind of mocked up how I would see multiple argument
types being used in the context that you shared with the CASE
expression:
?TACL ROUTINE
#FRAME
#PUSH JOB_ID MIN_JOB MAX_JOB
#SETMANY MIN_JOB MAX_JOB , 1 3
[#DEF VALID_KEYWORDS TEXT |BODY| THISJOB THATJOB SOMEOTHERJOB]
[#CASE
[#ARGUMENT/VALUE JOB_ID/
NUMBER/MINIMUM [MIN_JOB],MAXIMUM [MAX_JOB]/
KEYWORD/WORDLIST [VALID_KEYWORDS]/
STRING
OTHERWISE
]
| 1 |
#OUTPUT VALID JOB NUMBER = [JOB_ID]
| 2 |
#OUTPUT VALID KEYWORD = [JOB_ID]
| 3 |
#OUTPUT VALID STRING = [JOB_ID]
| OTHERWISE |
#OUTPUT NOT A NUMBER, KEYWORD, OR A STRING
#OUTPUT MUST BE ONE OF:
#OUTPUT A NUMBER IN THE RANGE OF: [MIN_JOB] TO [MAX_JOB]
#OUTPUT A KEYWORD IN THIS LIST: [VALID_KEYWORDS]
#OUTPUT OR A STRING OF CHARACTERS
#RETURN
]
#OUTPUT
#OUTPUT NOW WE ARE USING ARGUMENT [JOB_ID] !!!
TIME
#UNFRAME

How to conditionally transform text in a column in power query?

I am building a workbook in PowerBI and I have the need for doing a conditional appending of text to column A if it meets a certain criteria. Specifically, if column A does not end with ".html" then I want to append the text ".html" to the column.
A sample of the data would look like this:
URL | Visits
site.com/page1.html | 5
site.com/page2.html | 12
site.com/page3 | 15
site.com/page4.html | 8
where the desired output would look like this:
URL | Visits
site.com/page1.html | 5
site.com/page2.html | 12
site.com/page3.html | 15
site.com/page4.html | 8
I have tried using the code:
#"CurrentLine" = Table.TransformColumns(#"PreviousLine", {{"URL", each if Text.EndsWith([URL],".html") = false then _ & ".html" else "URL", type text}})
But that returns an error "cannot apply field access to the type Text".
I can achieve the desired output in a very roundabout way if I use an AddColumn to store the criteria value, and then another AddColumn to store the new appended value, but this seems like an extremely overkill way to approach doing a single transformation to a column. (I am specifically looking to avoid this as I have about 10 or so transformations and don't want to have so many columns to add and cleanup if there is a more succinct way of coding)
You don't want [URL] inside Text.EndWith. Try this:
= Table.TransformColumns(#"PreviousLine",
{{"URL", each if Text.EndsWith(_, ".html") then _ else _ & ".html", type text}}
)

BIRT: Align rows in list element

I'm using the Birt list element to display my data from left to right. (see this question as reference). Eg. List element with a Grid in details and the grid set to inline.
The issue I'm facing now is, that the different rows in the grid are not aligned left to right (probably due to some rows having empty values in some fields). How can I force BIRT to align properly?
EDIT:
This is especially also a problem with longer text that wraps to more than 1 line. The wrapping /multiple lines should be reflected by all list elements in that "row of the output".
Unfortunately, I don't see any chance to accomplish this easily in the generic case - that is, if the number of records is unknown in advance, so you'd need more than one line:
student1 student2 student3
student4 student5
Let's call those line "main lines". One main line can contain up to 3 records. The number 3 may be different in your case, but we can assume it is a constant, since (at least for PDF reports) the paper width is restricted.
A possible solution could work like this:
In your data set, add two columns for each row: MAIN_LINE_NUM and COLUMN_NUM, where the meaning is obvious. For example, this could be done with pure SQL using analytic functions (untested):
select ...,
trunc((row_number() over (order by ...whatever...) - 1) / 3) + 1 as MAIN_LINE_NUM,
mod(row_number() over (order by ...whatever...) - 1), 3) +1 as COLUMN_NUM
from ...
order by ...whatever... -- The order must be the same as above.
Now you know where each record should go.
The next task is to transform the result set into a form where each record looks like this (for the example, think that you have 3 properties STUDENT_ID, NAME, ADDRESS for each student):
MAIN_LINE
STUDENT_ID_1
NAME_1
ADDRESS_1
STUDENT_ID_2
NAME_2
ADDRESS_2
STUDENT_ID_3
NAME_3
ADDRESS_3
You get the picture...
The SQL trick to achieve this is one that one should know.
I'll show this for the STUDENT_ID_1, STUDENT_ID_2 and NAME_1 column as an example:
with my_data as
( ... the query shown above including MAIN_LINE_NUM and COLUMN_NUM ...
)
select MAIN_LINE_NUM,
max(case when COLUMN_NUM=1 then STUDENT_ID else null end) as STUDENT_ID_1,
max(case when COLUMN_NUM=2 then STUDENT_ID else null end) as STUDENT_ID_2,
...
max(case when COLUMN_NUM=1 then NAME else null end) as NAME_1,
...
from my_data
group by MAIN_LINE_NUM
order by MAIN_LINE_NUM
As you see, this is quite clumsy if you need a lot of different columns.
On the other hand, this makes the output a lot easier.
Create a table item for your dat set, with 3 columns (for 1, 2, 3). It's best to not drag the dataset into the layout. Instead, use the "Insert element" context menu.
You need a detail row for each of the columns (STUDENT_ID, NAME, ADDRESS). So, add two more details rows (the default is one detail row).
Add header labels manually, if you like, or remove the header row if you don't need it (which is what I assume).
Remove the footer row, as you probably don't need it.
Drag the columns to the corresponding position in your table.
The table item should look like this now (data items):
+--------------+--------------+-------------+
+ STUDENT_ID_1 | STUDENT_ID_2 | STUDENT_ID3 |
+--------------+--------------+-------------+
+ NAME_1 | NAME_2 | NAME_3 |
+--------------+--------------+-------------+
+ ADDRESS_1 | ADDRESS_2 | ADDRESS_3 |
+--------------+--------------+-------------+
That's it!
This is one of the few examples where BIRT sucks IMHO in comparison to other tools like e.g. Oracle Reports - excuse my Klatchian.

Stata: Generating variables in a loop using tuples local macro

I need to generate all possible tuples of the integer numbers 1,2,3,4 (with exactly 2 items in each tuple).Then, I need to generate a set of variables that would correspond to the resulting six tuples. Each variable name should contain a reference to a tuple and the value of each variable should be a string version of a tuple itself, as illustrated below:
+--------+--------+--------+--------+--------+--------+
| var_12 | var_13 | var_14 | var_23 | var_24 | var_34 |
+--------+--------+--------+--------+--------+--------+
| 12 | 13 | 14 | 23 | 24 | 34 |
+--------+--------+--------+--------+--------+--------+
While the tuples are generated by using the tuples user-written command (for details, see http://ideas.repec.org/c/boc/bocode/s456797.html), I am stumbling with generating new variables and assigning values to them in a loop. The code looks as follows and results in a syntax error which presumably stems from using local tuples macros incorrectly, and I would greatly appreciate if someone could help me solving it.
tuples 1 2 3 4, display min(2) max(2)
forval i = 1/`ntuples' {
gen v`i'=`tuple`i''
rename v`i' var_`tuple`i''
}
tuples is a user-written command from SSC. Over at www.statalist.org you would be expected to explain where it comes from, and that's a very good idea here too.
In your case, you want say integers such as 12 to represent a tuple such as "1 2" but the latter looks malformed to Stata when you are creating a numeric variable. Stata certainly won't elide the space(s) even if all characters presented otherwise are numeric. So you need to do that explicitly. At the same name giving a variable one name and then promptly renaming it can be compressed.
forval i = 1/`ntuples' {
local I : subinstr local tuple`i' " " "", all
gen var_`I' = `I'
}
Creating a string variable for the tuple with space included would make part of that unnecessary, but the space is still not allowed in the variable name:
forval i = 1/`ntuples' {
local I : subinstr local tuple`i' " " "_", all
gen var_`I' = "`tuple`i''"
}
If this is the whole of your problem, it would have been quicker to write out 6 generate statements! If this is a toy problem representative of something larger, watch out that say "1 23" and "12 3" would both be mapped to "123", so eliding the spaces is unambiguous only with single digit integers; hence the appeal of holding strings as such.
I am still curious how holding the same tuple in every observation of a variable is a good idea; perhaps your larger purpose would be better met by using string scalars or the local macros themselves.

about .replace in Velocity

I have a Pipe | delimited file I'm sending out and in a string field the client is using Pipes as just a random character to separate points.
Example. This is what text they have in the field.
Encore AWD | Leather | Navigation | Sunroof | Back Up Camera | USB | Bluetooth
I need to replace the | with a - and this is the code I'm trying.
#set ($va.list_comment = $va.listing_comment.replace("|", "-"))
it is still outputting the | characters.
Anyone have any ideas what I could be doing wrong here?
You cannot assign a new value into an object. If you're using the latest version of Velocity, then such an assignment would work if there is a setList_comment method, or if $va is a Map. Otherwise, you would have to just create a new variable that would host the new value and use it:
#set ($fixedListing = $va.listing_comment.replace("|", "-"))
$fixedListing
Or if you don't need that value for anything else than just printing it once, skip the assignment completely and just print the outcome:
$va.listing_comment.replace("|", "-")
If that still doesn't work, make sure the value returned is indeed a java.lang.String and not something else:
$va.listing_comment.class