How to print unique values in xquery - xquery

I have the following XQuery function with me.
declare function local:format($input as element() *) as element() *{
for $v in
$input
return if
(((for $x in $input return $x)/#one=$v/#two) and ((for $y in $input return $y)/#two=$v/#one))
then
(
)
else {$v}
};
The input to the above function is :
** <pair two="IN011" one="IN007"> David Emma </pair> **
** <pair two="IN007" one="IN011"> Emma David </pair> **
But the output I want is :
** <pair two="IN011" one="IN007"> David Emma </pair> **
or else:
** <pair two="IN007" one="IN011"> Emma David </pair> **
That is, I want it to be printed only once.
The functionality of the above function should be something like that. But, it's incomplete.I tried every possible way. Please help to get the output I've mentioned above

What you want to do is normalize the values in your source sequence and return the distinct values based on the normalized strings:
declare function local:normalize(
$label as xs:string
) as xs:string
{
string-join(
for $t in tokenize($label, '\s+')
order by $t
return $t)
};
let $pairs := (<pair two="IN011" one="IN007"> David Emma </pair>,
<pair two="IN007" one="IN011"> Emma David </pair>)
let $pairs-normalized :=
for $p in $pairs
return element pair {
$p/#*,
attribute hash { local:normalize($p) },
$p/node()
}
return $pairs-normalized[index-of($pairs-normalized/#hash, #hash)[1]]
=> <pair two="IN011" one="IN007" hash="DavidEmma"> David Emma </pair>
Another way of doing it is using distinct-values:
for $d in distinct-values($pairs-normalized/#hash)
return ($pairs-normalized[#hash = $d])[1]

Related

Ada 202x proposal # restriction rationale?

I have a question about the proposed Ada 202x standard. Specifically I am wondering about the constraints on the target name (#) feature. It appears as though this feature will only be available in assignment statements and not in record or array aggregates. What is the rationale behind this restriction?
To explain why I think it would be useful to broaden the scope of target name. Compare these two functions.
Implementation as I understand the proposed standard:
function Mutate (State : Some_State) return Some_State is (State with delta
Internal_Component => (State.Internal_Component with delta
Component_Array => (State.Internal_Component.Component_Array with delta
Array_Index => State.Internal_Component.Component_Array (Array_Index) + 1,
Other_Index => State.Internal_Component.Component_Array (Other_Index) - 1)));
If the target name feature were extended to aggregates then this could be:
function Mutate (State : Some_State) return Some_State is (State with delta
Internal_Component => (# with delta -- # is State.Internal_Component
Component_Array => (# with delta -- # is State.Internal_Component.Component_Array
Array_Index => # + 1, -- # is State.Internal_Component.Component_Array (Array_Index)
Other_Index => # - 1))); -- # is State.Internal_Component.Component_Array (Other_Index)
If delta aggregates could implicitly nest this could result in the very clean:
function Clean_Mutate (State : Some_State) return Some_State is (State with delta
Internal_Component.Component_Array => # with delta (
Array_Index => # + 1,
Other_Index => # - 1));
Of course as written one could use:
function Mutate (State : Some_State) return Some_State is
Result : Some_State := State;
begin
Result.Internal_Component.Component_Array (Array_Index) := # + 1;
Result.Internal_Component.Component_Array (Other_Index) := # - 1;
return Result;
end Mutate;
But this is still not quite as clean, and it severely hampers target name's use in non-assignment expressions.

Round time in Xpath

What is the simplest and correct way to round the time and dateTime in XPath?
For example, how to define a function local:round-time-to-minutes in such way that the following test-case:
let $t1 := xs:time( "12:58:37" )
let $t2 := local:round-time-to-minutes( $t1 )
return format-time( $t2, '[H01]:[m01]:[s01]' )
will return "12:59:00".
Don't sure what is better in case of "23:59:31" — to return "00:00:00" or to raise a dynamic error.
And similar function local:round-datetime-to-minutes to handle dateTime?
(it doesn't have such edge case as above)
Let these functions use "round half towards positive infinity" rule, where half is 30.0 seconds.
This is how the solution proposed by #michael.hor257k would look in XQuery:
declare variable $ONE_MIN := xs:dayTimeDuration("PT1M");
declare variable $MIDNIGHT := xs:time("00:00:00");
declare function local:round-time-to-minutes($time) {
$MIDNIGHT + round(($time - $MIDNIGHT) div $ONE_MIN) * $ONE_MIN
};
Another solution is to subtract the number of second from the given dateTime and add one minute (60 seconds) if the number of seconds is not less than 30.
To convert a number of seconds into duration we multiple it on 1S duration (actually, this operation can be eliminated by a compiler).
declare function local:round-time-to-minutes ( $time as xs:time ) {
let $s := seconds-from-time( $time )
return $time - xs:dayTimeDuration('PT1S') * ( $s - 60 * ($s idiv 30) )
};
declare function local:round-dateTime-to-minutes ( $dt as xs:dateTime ) {
let $s := seconds-from-dateTime( $dt )
return $dt - xs:dayTimeDuration('PT1S') * ( $s - 60 * ($s idiv 30) )
};
This solution is uniform for the cases of xs:time and xs:dateTime types.

Recursion in Go

I'm a Javascript developer by trade and decided to give Go a spin. As a learning exercise I decided to port a function in one of my node projects, but can't get it working for the life of me. The function's purpose is to display all of the valid english words that can be made from the letters present in a different word (I'm building a multiplayer version of Text Twist). For example, findAllWords("dances") would return ['can','scan','dance','dances',etc...]. I've achieved this by recursing on a trie built from an English word list.
Here is the function's implementation in Javascript:
self.findAllWords = function(letters = [], trie = dictionary, curString = '') {
let words = [];
letters = typeof letters === 'string' ? letters.split('') : letters;
letters.forEach( (letter,i,ar) => {
if (!trie[letter]) return;
let curWord = curString + letter;
let newTrie = trie[letter];
let newLetters = [...ar.slice(0,i),...ar.slice(i+1)];
if (trie[letter][FLAG_INDEX]) words.push(curWord);
if (self.isValidPrefix(curWord, dictionary)) words = [...words,...self.findAllWords(newLetters,newTrie,curWord)];
});
return uniq(words);
}
and here's my attempt at replicating it in Go (using this trie implementation):
func FindAllWords(letters []rune, node *Node, curString string) []string {
words := []string{}
for i, let := range letters {
n, ok := node.Children()[let]
if !ok {
return words
}
curWord := curString + string(n.val)
newLetters := []rune{}
newLetters = append(newLetters, letters[:i]...)
newLetters = append(newLetters, letters[i+1:]...)
if n.term {
words = append(words, curWord)
}
words = append(words, FindAllWords(newLetters, n, curWord)...)
}
return words
}
Would love to know why this is failing, how I can get it working, and any conventions I'm abusing/not making use of. Thanks!
This may or may not be the only problem with the Go code, but the return statement in the for loop is not doing the same thing as the return statement in the javascript forEach.
Return within the anonymous function in the javascript code returns from the anonymous function to within the findAllWords function. Return within the Go for loop returns from FindAllWords. This will prematurely stop the operation when it comes across a letter not within the root of the trie. I presume the issue you are having is the []string being returned is empty or incomplete.
Instead of return words, you should use break.
OK, there are two problems in OP's implementation:
The action of the if block checking for child existence should "continue" the loop instead of returning words as a result (to try other tree branches).
The if block condition checking whether the current node is a terminal (word) must be changed to accomodate github.com/derekparker/trie author's design decision of storing the terminal node as a child of the node corresponding to the last letter of the word, keyed in its parent as the 0 rune.
Here's the working version:
func FindAllWords(letters []rune, node *trie.Node, curString string) []string {
words := []string{}
for i, let := range letters {
n, ok := node.Children()[let]
if !ok {
continue
}
curWord := curString + string(n.Val())
newLetters := []rune{}
newLetters = append(newLetters, letters[:i]...)
newLetters = append(newLetters, letters[i+1:]...)
if n.Children()[0x0] != nil {
words = append(words, curWord)
}
words = append(words, FindAllWords(newLetters, n, curWord)...)
}
return words
}
Here's a somewhat more readable version (to my taste, of course):
func FindAllWords2(s string, n *trie.Node, w string) []string {
r := []string{}
for i, l := range s {
n1, ok := n.Children()[l]
if !ok {
continue
}
s1 := s[:i] + s[i+1:]
w1 := w + string(l)
if n1.Children()[0x0] != nil {
r = append(r, w1)
}
r = append(r, FindAllWords2(s1, n1, w1)...)
}
return r
}
The second problem is of course coming from depending on an external library with a somewhat leaky API which exposes implementation details to the client code.
To avoid such kind of trouble for this simple case, I would recommend to build a simple trie implementation which can come as easy as this:
type Node struct {
Char rune
Term bool
Children map[rune]*Node
}
func (n *Node) Add(s []rune) {
if len(s) == 0 {
n.Term = true
return
}
r := s[0]
c, ok := n.Children[r]
if !ok {
c = &Node{Char: r, Children: make(map[rune]*Node)}
n.Children[r] = c
}
c.Add(s[1:])
}
func Empty() *Node {
return &Node{Children: make(map[rune]*Node)}
}
Using that structure this is how I loaded an english wordlist:
func English() *Node {
f, err := os.Open("/usr/share/dict/american-english")
if err != nil {
panic(err)
}
defer f.Close()
t := Empty()
s := bufio.NewScanner(f)
for s.Scan() {
t.Add([]rune(strings.ToLower(s.Text())))
}
return t
}
That structure can be used in the same algorithm with very little modification and no implementation misteries:
func FindAllWords3(s string, n *Node, w string) []string {
r := []string{}
for i, l := range s {
n1, ok := n.Children[l]
if !ok {
continue
}
s1 := s[:i] + s[i+1:]
w1 := w + string(l)
if n1.Term {
r = append(r, w1)
}
r = append(r, FindAllWords3(s1, n1, w1)...)
}
return r
}
Here are the results of the three implementations above applied to the word "dances" and the same english wordlist loaded above:
[d dan dance dances dane danes dean deans den dena dens dec a ad aden ads an and andes ac acne ace aced aces as ascend n nd na ne ned c cd ca cad cads can cane caned canes cans case cased cs e ed edna end ends es s sad sade san sand sane sac sn snead sc scad scan se sedan sedna sea sean sen send sec]
[d dan dance dances dane danes dean deans den dena dens dec a ad aden ads an and andes ac acne ace aced aces as ascend n nd na ne ned c cd ca cad cads can cane caned canes cans case cased cs e ed edna end ends es s sad sade san sand sane sac sn snead sc scad scan se sedan sedna sea sean sen send sec]
[d dan dance dances dane danes dean deans den dena dens dec a ad aden ads an and andes ac acne ace aced aces as ascend n nd na ne ned c cd ca cad cads can cane caned canes cans case cased cs e ed edna end ends es s sad sade san sand sane sac sn snead sc scad scan se sedan sedna sea sean sen send sec]

XQuery difference between same function different implementation

Return the number of cycles:
let $bd := doc("document")
return count ( for $c in $bd//cycle
where $c[#id]
return $c
)
Every cycle has an ID, not important here but it is a must to specify it.
What is the difference between the above use of count and the below use of count?
let $bd := doc("document")
let $c := $bd//cycle[#id]
return count($c)
I dont know the difference between these 2 XQueries return same result but following the same pattern the next 2 queries should work but the 2nd one doesnt... Here they are:
The total of hours of modules which is above 100.
*Working query*
let $bd:=doc("document")
return sum (
for $m in $bd//module[#id]
where $m/hours>100
return $m/hours
)
*Not working query*
let $bd := doc("document")
for $c in $bd//module[#id]
where $c/hours>100
return sum($c/hours)
Id like to know why following the same "pattern" the second query is not working.
The output of the not working query is this one:
160 160 256 224 192 160
Its not the result i need, I want the sum of all them.
The first two expressions are functionally equivalent. The difference is the use of FLWOR vs. XPath to select your sequence.
In the second example, you are calling sum() on each item of the sequence ($c/hours), instead of on the sequence itself:
let $bd := doc("document")
return sum(
for $c in $bd//module[#id]
where $c/hours>100
return $c/hours)
You could also use XPath:
let $bd := doc("document")
let $c := $bd//module[#id][hours>100]
return sum($c/hours)
Or similarly assign the result of the FLWOR to a variable and sum that:
let $bd := doc("document")
let $c :=
for $m in $bd//module[#id]
where $m/hours>100
return $m/hours
return sum($c)

golang map prints out of order

Why is the map printing out of order, and how do I get it in to order?
package main
import (
"fmt"
)
type monthsType struct {
no int
text string
}
var months = map[int]string{
1:"January", 2:"Fabruary", 3:"March", 4:"April", 5:"May", 6:"June",
7:"July", 8:"August", 9:"September", 10:"October", 11:"Novenber", 12:"December",
}
func main(){
for no, month := range months {
fmt.Print(no)
fmt.Println("-" + month)
}
}
Prints out:
10-October
7-July
1-January
9-September
4-April
5-May
2-Fabruary
12-December
11-Novenber
6-June
8-August
3-March
Code:
func DemoSortMap() (int, error) {
fmt.Println("use an array to access items by number:")
am := [2]string{"jan", "feb"}
for i, n := range am {
fmt.Printf("%2d: %s\n", i, n)
}
fmt.Println("maps are non-sorted:")
mm := map[int]string{2: "feb", 1: "jan"}
for i, n := range mm {
fmt.Printf("%2d: %s\n", i, n)
}
fmt.Println("access items via sorted list of keys::")
si := make([]int, 0, len(mm))
for i := range mm {
si = append(si, i)
}
sort.Ints(si)
for _, i := range si {
fmt.Printf("%2d: %s\n", i, mm[i])
}
return 0, nil
}
(most of it stolen from M. Summerfield's book)
output:
use an array to access items by number:
0: jan
1: feb
maps are non-sorted:
2: feb
1: jan
access items via sorted list of keys::
1: jan
2: feb
Maps are not sorted so you may use a slice to sort your map. Mark Summerfield's book "Programming in Go" explains this on page 204 and is highly recommended.
This is very late answer, but from what I have read maps are unsorted by design, and are random as one should not rely on the order.
Besides using the sort package together with a second map, one can also use the fmt.Prinln(theMap), which will print the map sorted.
fmt: print maps in key-sorted order
This will print the map typically as follows:
map[key:value
key:value
key:value
]
But this might not be what you want...
By using the fmt.Sprint one can then manipulate the string if needed.
i.e.
s := fmt.Sprint(theMap)
s1 := s[4 : len(s)-1] // remove map[ and ]
fmt.Println(s1)

Resources