我有几个列表,可能是空的也可能不是。我想找到所有列表中出现的那些元素,但仅限于那些非空的列表。 我有这样的事情:
let $results :=
$list1 intersect
$list2 intersect
$list3 intersect
$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是一种功能性语言,它对我来说并不是那么自然(还)。
答案 0 :(得分:1)
您可以将其包装在函数中并检查输入列表,而不是直接使用内置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 :=
local:safe-intersect(
$list1,
local:safe-intersect(
$list2,
local:safe-intersect($list3, $list4)
)
)
...
答案 1 :(得分:0)
如果所有列表都是空的,您可以查看它们。如果是,请为其分配所有列表的并集。
对于我的例子,我使用了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)
,但这会导致双元素导致较大元素计数的交叉操作较慢。
答案 2 :(得分:0)
使用强>:
( $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)] )
在此表达式中,intersect
的每个参数都是$vN
,或者如果$vN
为空,则它是其余集合的并集。
这可以更紧凑地编写为:
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)] )
在以下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>
产生了想要的正确结果:
<num>01</num>