Xquery transform string to same number but with decimal dot - xquery

I am working with xQuery version 1.0 and I'm trying to transform a string of numbers to the same number but with a decimal dot. But here's my problem. The decimal dot should be placed according to a certain element value.
The message I'm trying to transform:
<AMOUNT
<VALUE>34221</VALUE>
<NUMOFDEC>1</NUMOFDEC>
<SIGN>+</SIGN>
<CURRENCY>EUR</CURRENCY>
<DRCR>C</DRCR>
</AMOUNT>
What I'm trying to achieve:
<prefix:Rates
<prefix:Amount currency="EUR">3422.1</prefix:Amount>
</prefix:Rates>
What did I try:
<prefix:Rates>
<prefix:Amount currency="{ data(AMOUNT/CURRENCY) }">{ ((data(AMOUNT/VALUE) div 10)) }</prefix:Amount>
</prefix:Rates>
The problem with the above transformation is that it's not dynamic. But as you can see there is an element <NUMOFDEC>1</NUMOFDEC>. Can I use that value in a certain formula to place the decimal dot according to this value?
EDIT (19th october 2022):
As a another user mentioned, there is recursion. Let's take this recursion from user #Michael Kay:
declare function f:two-to-the($n as xs:integer) as xs:integer {
if ($n = 0) then 1 else 2 * f:two-to-the($n - 1)
};
So how will I be able to apply this to my situation?

(div math:pow(10, AMOUNT/NUMOFDEC)) might do but I don't recall whether XQuery 1 supports the math namespace mathematical functions, namespace is e.g. math="http://www.w3.org/2005/xpath-functions/math", it might depend on your XQuery processor, I guess.

So I found a solution with an if-else statement. Unfortunately as another user mentioned, the mat:pow fucntion is not supported by Xquery 1.0.
Solution:
<prefix:Amount>{
(for $decimal in (data(AMOUNT/NUMOFDEC))
return if ($decimal = '1')
then ((data(AMOUNT/VALUE)) div 10)
else if ($decimal = '2')
then ((data(AMOUNT/VALUE)) div 100)
else ($decimal = '3')
then ((data(AMOUNT/VALUE)) div 1000)
else ((data(AMOUNT/VALUE)) div 10000))
}</prefix:Amount>
Is it fully dynamic? no. But it will do the trick for now.
EDIT (19th october 2022): The following recursion works!:
declare function xf:ten-to-the($decimal as xs:integer) as xs:integer {
if ($decimal = 0) then 1 else 10 * xf:ten-to-the($decimal - 1)
};

Related

Filter vertices on several properties - Julia

I am working on julia with the Metagraphs.jl library.
In order to conduct an optimization problem, I would like to get the set/list of edges in the graph that point to a special set of vertices having 2 particular properties in common.
My first guess was to first get the set/list of vertices. But I am facing a first issue which is that the filter_vertices function doesn't seem to accept to apply a filter on more than one property.
Here is below an example of what I would like to do:
g = DiGraph(5)
mg = MetaDiGraph(g, 1.0)
add_vertex!(mg)
add_edge!(mg,1,2)
add_edge!(mg,1,3)
add_edge!(mg,1,4)
add_edge!(mg,2,5)
add_edge!(mg,3,5)
add_edge!(mg,5,6)
add_edge!(mg,4,6)
set_props!(mg,3,Dict(:prop1=>1,:prop2=>2))
set_props!(mg,1,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,2,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,4,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,5,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,6,Dict(:prop1=>0,:prop2=>0))
col=collect(filter_vertices(mg,:prop1,1,:prop2,2))
And I want col to find vertex 3 and no others.
But the filter_vertices would only admit one property at a time and then it makes it more costly to do a loop with 2 filters and then try to compare in order to sort a list with the vertices that have both properties.
Considering the size of my graph I would like to avoid defining this set with multiple and costly loops. Would any one of you have an idea of how to solve this issue in an easy and soft way?
I ended up making this to answer my own question:
fil3=Array{Int64,1}()
fil1=filter_vertices(mg,:prop1,1)
for f in fil1
if get_prop(mg,f,:prop2)==2
push!(fil3,f)
end
end
println(fil3)
But tell me if you get anything more interesting
Thanks for your help!
Please provide a minimal working example in a way we can simply copy and paste, and start right away. Please also indicate where the problem occurs in the code. Below is an example for your scenario:
Pkg.add("MetaGraphs")
using LightGraphs, MetaGraphs
g = DiGraph(5)
mg = MetaDiGraph(g, 1.0)
add_vertex!(mg)
add_edge!(mg,1,2)
add_edge!(mg,1,3)
add_edge!(mg,1,4)
add_edge!(mg,2,5)
add_edge!(mg,3,5)
add_edge!(mg,5,6)
add_edge!(mg,4,6)
set_props!(mg,3,Dict(:prop1=>1,:prop2=>2))
set_props!(mg,1,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,2,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,4,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,5,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,6,Dict(:prop1=>0,:prop2=>0))
function my_vertex_filter(g::AbstractMetaGraph, v::Integer, prop1, prop2)
return has_prop(g, v, :prop1) && get_prop(g, v, :prop1) == prop1 &&
has_prop(g, v, :prop2) && get_prop(g, v, :prop2) == prop2
end
prop1 = 1
prop2 = 2
col = collect(filter_vertices(mg, (g,v)->my_vertex_filter(g,v,prop1,prop2)))
# returns Int[3]
Please check ?filter_vertices --- it gives you a hint on what/how to write to define your custom filter.
EDIT. For filtering the edges, you can have a look at ?filter_edges to see what you need to achieve the edge filtering. Append the below code excerpt to the solution above to get your results:
function my_edge_filter(g, e, prop1, prop2)
v = dst(e) # get the edge's destination vertex
return my_vertex_filter(g, v, prop1, prop2)
end
myedges = collect(filter_edges(mg, (g,e)->my_edge_filter(g,e,prop1,prop2)))
# returns [Edge 1 => 3]
I found this solution:
function filter_function1(g,prop1,prop2)
fil1=filter_vertices(g,:prop1,prop1)
fil2=filter_vertices(g,:prop2,prop2)
filter=intersect(fil1,fil2)
return filter
end
This seems to work and is quite easy to implement.
Just I don't know if the filter_vertices function is taking a lot of computational power.
Otherwise a simple loop like this seems to also work:
function filter_function2(g,prop1,prop2)
filter=Set{Int64}()
fil1=filter_vertices(g,:prop1,prop1)
for f in fil1
if get_prop(g,f,:prop2)==prop2
push!(filter,f)
end
end
return filter
end
I am open to any other answers if you have some more elegant ones.

Get word at position in Atom

From a linter provider, I receive a Point compatible array(line, column) where the error occured. Now I would like to hightlight the word surrounding that point, basically the result one would get if that exact point was double-clicked in the editor. Something like
const range = textEditor.getWordAtPosition(point)
Is what I hoped for, but couldn't find in the documentation.
Thanks for your help!
After looking around for a while, there seems to be no API method for the given need. I ended up writing a small helper function based upon this answer:
function getWordAtPosition(line, pos) {
// Perform type conversions.
line = String(line);
pos = Number(pos) >>> 0;
// Search for the word's beginning and end.
const left = Math.max.apply(null, [/\((?=[^(]*$)/,/\)(?=[^)]*$)/, /\,(?=[^,]*$)/, /\[(?=[^[]*$)/, /\](?=[^]]*$)/, /\;(?=[^;]*$)/, /\.(?=[^.]*$)/, /\s(?=[^\s]*$)/].map(x => line.slice(0, pos).search(x))) + 1
let right = line.slice(pos).search(/\s|\(|\)|\,|\.|\[|\]|\;/)
// The last word in the string is a special case.
if (right < 0) {
right = line.length - 1
}
// Return the word, using the located bounds to extract it from the string.
return str.slice(left, right + pos)
}
Here, the beginning of the word is determined by the latest occurance of one of the characters (),.[]; or a blank.
The end of the word is determined by the same characters, however here the first occurance is taken as a delimeter.
Given the original context, the function can the be called using the API method ::lineTextForBufferRow and the desired postion (column) as follows:
const range = getWordAtPosition(textEditor.lineTextForBufferRow(bufferRow), 10)

R: Iterating Over the List

I am trying to implement following algorithm in R:
Iterate(Cell: top)
While (top != null)
Print top.Value
top = top.Next
End While
End Iterate
Basically, given a list, the algorithm should break as soon as it hits 'null' even when the list is not over.
myls<-list('africa','america south','asia','antarctica','australasia',NULL,'europe','america north')
I had to add a for loop for using is.null() function, but following code is disaster and I need your help to fix it.
Cell <- function(top) {
#This algorithm examines every cell in the linked list, so if the list contains N cells,
#it has run time O(N).
for (i in 1:length(top)){
while(is.null(top[[i]]) !=TRUE){
print(top)
top = next(top)
}
}
}
You may run this function using:
Cell(myls)
You were close but there is no need to use for(...) in this
construction.
Cell <- function(top){
i = 1
while(i <= length(top) && !is.null(top[[i]])){
print(top[[i]])
i = i + 1
}
}
As you see I've added one extra condition to the while loop: i <= length(top) this is to make sure you don't go beyond the length of the
list in case there no null items.
However you can use a for loop with this construction:
Cell <- function(top){
for(i in 1:length(top)){
if(is.null(top[[i]])) break
print(top[[i]])
}
}
Alternatively you can use this code without a for/while construction:
myls[1:(which(sapply(myls, is.null))[1]-1)]
Check this out: It runs one by one for all the values in myls and prints them but If it encounters NULL value it breaks.
for (val in myls) {
if (is.null(val)){
break
}
print(val)
}
Let me know in case of any query.

Rounding to nearest or up in SQLite

I've got an existing calculation (in SQL) which contains several formulas involving rounding. Now I've got to make sure that the rounding uses the half up tie-breaking alorithm.
It appears that by default, SQLite's round function uses the half to even algorithm.
Is there a simple way to change that to half up?
The built-in round function rounds towards negative infinity.
There is no simply way to do half-to-even directly in SQL.
You'd have to install your own custom rounding function, or modify the SQLite source code:
if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
r = (double)((sqlite_int64)(r+0.5));
}else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
r = -(double)((sqlite_int64)((-r)+0.5));
}else{
zBuf = sqlite3_mprintf("%.*f",n,r);
sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
}

systemverilog constraint dist using weights array

I need to be able to set a constraint dist with 64 different, changeble weights:
I need to random pick an index of range 0~63, when every index has its own weight / probability to be chosen.
I can write something like:
constraint pick_chan_constraint {pick_channel dist{
0:=channel_weight[0], 1:=channel_weight[1], 2:=channel_weight[2],
3:=channel_weight[3], 4:=channel_weight[4], 5:=channel_weight[5],
6:=channel_weight[6], 7:=channel_weight[7], 8:=channel_weight[8],
9:=channel_weight[9], 10:=channel_weight[10], 11:=channel_weight[11],
12:=channel_weight[12], 13:=channel_weight[13],
14:=channel_weight[14], … ...
NUM_OF_CHANS-1 := channel_weight[NUM_OF_CHANS-1] }}
Obviously it's bad writing and a bad idea, out of 2 reasons:
No flexibility- if NUM_OF_CHANS changes, I'll need to change the code.
It's long and ugly and almost unreadable.
Any ideas?
Thanks
IEEE Std 1800-2012 § 18.5.4 Distribution shows the dist_list needs to be a list of dist_items and a dist_item is defined as a value_range [ dist_weight ]. In other words the distribution needs to be listed out.
Instead of using a constraint you could create a queue array (§ 7.10 Queues) and then use the shuffle method (§ 7.12.2 Array ordering methods). Example:
int channel_weight [64];
int pick_channel;
int weight_chain [$];
weight_chain.delete(); // make sure it is empty
foreach (channel_weight[i]) begin
repeat (channel_weight[i]) begin
weight_chain.push_back(i);
end
end
weight_chain.shuffle(); // randomize order
assert( weight_chain.size() > 0) else $error("all channel_weights are 0");
pick_channel = weight_chain[0];

Resources