在XQuery中从交叉点排除空列表
我有几个清单,可能是空的,也可能不是空的。我想找到所有列表中出现的元素,但只针对那些不是空的列表。 我有这样的想法:在XQuery中从交叉点排除空列表,xquery,Xquery,我有几个清单,可能是空的,也可能不是空的。我想找到所有列表中出现的元素,但只针对那些不是空的列表。 我有这样的想法: let $results := $list1 intersect $list2 intersect $list3 intersect $list4 let $results := local:safe-intersect( $list1, local:safe-intersect( $l
let $results :=
$list1 intersect
$list2 intersect
$list3 intersect
$list4
let $results :=
local:safe-intersect(
$list1,
local:safe-intersect(
$list2,
local:safe-intersect($list3, $list4)
)
)
...
但是,如果任何列表为空,则该表达式将返回一个空列表。如果列表为空,是否有任何方法可以将其从交叉点中排除
解决方案:
这是我最终使用的解决方案,基于Ranon提供的答案
let $union := $list1 | $list2 | $list3 | $list4
let $results :=
(if ($list1) then $list1 else $union) intersect
(if ($list2) then $list2 else $union) intersect
(if ($list3) then $list3 else $union) intersect
(if ($list4) then $list4 else $union)
我要感谢所有作出贡献的人。来自面向对象和过程的背景,而XQuery是一种函数式语言,因此我对它的理解并不自然。如果所有列表都是空的,您可以检查它们。如果是,请将所有列表的并集指定给它们 在我的示例中,我使用了intersect和union的functx实现来实现序列的相交。也许应该编写一些函数来避免冗余代码,但为了说明这一点,这段代码很好:
import module namespace functx = "http://www.functx.com" at ".../functx-1.0-nodoc-2007-01.xq";
let $list1 := (1,2,3)
let $list2 := (1,3)
let $list3 := ()
let $union := functx:value-union($list1, functx:value-union($list2, $list3))
let $list1a := if (count($list1) != 0) then $list1 else $union
let $list2a := if (count($list2) != 0) then $list2 else $union
let $list3a := if (count($list3) != 0) then $list3 else $union
return functx:value-intersect($list1a, functx:value-intersect($list2a, $list3a))
$union
也可以写为($list1,$list2,$list3)
,但这将导致双元素,从而导致较大元素计数的交叉操作较慢。如果所有列表为空,则可以检查它们。如果是,请将所有列表的并集指定给它们
在我的示例中,我使用了intersect和union的functx实现来实现序列的相交。也许应该编写一些函数来避免冗余代码,但为了说明这一点,这段代码很好:
import module namespace functx = "http://www.functx.com" at ".../functx-1.0-nodoc-2007-01.xq";
let $list1 := (1,2,3)
let $list2 := (1,3)
let $list3 := ()
let $union := functx:value-union($list1, functx:value-union($list2, $list3))
let $list1a := if (count($list1) != 0) then $list1 else $union
let $list2a := if (count($list2) != 0) then $list2 else $union
let $list3a := if (count($list3) != 0) then $list3 else $union
return functx:value-intersect($list1a, functx:value-intersect($list2a, $list3a))
$union
也可以写为($list1,$list2,$list3)
,但这将导致双元素,从而导致较大元素计数的相交操作较慢。您可以将其包装在函数中并检查输入列表,而不是直接使用内置的intersect
declare function local:safe-intersect($xs, $ys) {
if(exists($xs) and exists($ys))
then $xs intersect $ys
else ($xs, $ys) (: at least one is empty :)
};
那么您的示例如下所示:
let $results :=
$list1 intersect
$list2 intersect
$list3 intersect
$list4
let $results :=
local:safe-intersect(
$list1,
local:safe-intersect(
$list2,
local:safe-intersect($list3, $list4)
)
)
...
您可以将其包装在函数中并检查输入列表,而不是直接使用内置的
intersect
:
declare function local:safe-intersect($xs, $ys) {
if(exists($xs) and exists($ys))
then $xs intersect $ys
else ($xs, $ys) (: at least one is empty :)
};
那么您的示例如下所示:
let $results :=
$list1 intersect
$list2 intersect
$list3 intersect
$list4
let $results :=
local:safe-intersect(
$list1,
local:safe-intersect(
$list2,
local:safe-intersect($list3, $list4)
)
)
...
使用:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
在此表达式中,intersect
的每个参数要么是$vN
,要么,如果$vN
为空,则是其余集合的并集
这可以写得更简洁,如下所示:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
下面是一个完整的示例:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
在以下XML文档上计算此XQuery表达式时(使用Saxon 9.3.04 EE):
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
01
02
03
04
05
06
07
08
09
10
生成所需的正确结果:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
01
使用:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
在此表达式中,intersect
的每个参数要么是$vN
,要么,如果$vN
为空,则是其余集合的并集
这可以写得更简洁,如下所示:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
下面是一个完整的示例:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
在以下XML文档上计算此XQuery表达式时(使用Saxon 9.3.04 EE):
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
01
02
03
04
05
06
07
08
09
10
生成所需的正确结果:
( $vL1 | ($vL2 | $vL3 | $vL4)[not($vL1)] )
intersect
( $vL2 | ($vL3 | $vL4 | $vL1)[not($vL2)] )
intersect
( $vL3 | ($vL4 | $vL1 | $vL2)[not($vL3)] )
intersect
( $vL4 | ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
$vL2 := /*/*[. mod 3 eq 1],
$vL3 := /*/*[. mod 4 eq 1],
$vL4 := /*/*[. mod 5 eq 1],
$vUniverse := $vL1 | $vL2 | $vL3 | $vL4
return
( $vL1 | $vUniverse [not($vL1)] )
intersect
( $vL2 | $vUniverse [not($vL2)] )
intersect
( $vL3 | $vUniverse [not($vL3)] )
intersect
( $vL4 | $vUniverse [not($vL4)] )
<num>01</num>
01
您确定这是正确的吗?我认为这个解决方案看起来是最优雅的,但仔细观察,结果似乎是所有列表的联合。一个测试证实了我的怀疑。@NobleK:是的,我总是通过实际运行来测试我的代码。我用一个完整的代码示例更新了我的答案,显示了这一点。出现问题的原因可能是您没有完全复制和粘贴代码,并且省略了括号。括号很重要,因为interscect
比union
具有更高的优先级。我无意侮辱你或其他什么。我以前在这里读过你们关于XQuery的一些回答,我相信你们知道自己在说什么。只是你的方法似乎真的不适合我(是的,我记得所有的括号)。我怀疑这可能与我正在使用的eXist XQuery引擎有关。我注意到它有时表现得很奇怪,产生的结果与Saxon不一样。@NobleK:NP,如果您能分享您的观察结果,eXist开发人员将不胜感激。当您运行我的代码示例时,您不会得到与我相同的结果吗?您确定这是正确的吗?我认为这个解决方案看起来是最优雅的,但仔细观察,结果似乎是所有列表的联合。一个测试证实了我的怀疑。@NobleK:是的,我总是通过实际运行来测试我的代码。我用一个完整的代码示例更新了我的答案,显示了这一点。出现问题的原因可能是您没有完全复制和粘贴代码,并且省略了括号。括号很重要,因为interscect
比union
具有更高的优先级。我无意侮辱你或其他什么。我以前在这里读过你们关于XQuery的一些回答,我相信你们知道自己在说什么。只是你的方法似乎真的不适合我(是的,我记得所有的括号)。我怀疑这可能与我正在使用的eXist XQuery引擎有关。我注意到它有时表现得很奇怪,产生的结果与Saxon不一样。@NobleK:NP,如果您能分享您的观察结果,eXist开发人员将不胜感激。当您运行我的代码示例时,您不会得到与我相同的结果吗?嗨,Ranon。我测试了这个,效果很好。我只是重新编写它来使用常规的并集和交集(因为我实际上想检查身份),我还只是测试存在性,而不是计数。我已经用我的密码更新了问题。你好,拉农。我测试了这个,效果很好。我只是用普通的工会和中间人重新编写了它