gpt4 book ai didi

xquery - 使用 XQuery 进行递归的示例

转载 作者:行者123 更新时间:2023-12-02 05:59:26 24 4
gpt4 key购买 nike

我有一个如下所示的数据库(通过$database访问它):

<country car_code="F" area="547030" capital="cty-france-paris">
<name>France</name>
<border country="AND" length="60"/>
<border country="E" length="623"/>
<border country="D" length="451"/>
<border country="I" length="488"/>
<border country="CH" length="573"/>
<border country="B" length="620"/>
<border country="L" length="73"/>
<border country="MC" length="4.4"/>
</country>

.....
other countries

我想编写一个函数,给出从法国(或任何其他国家)通过陆地边界可到达的所有国家的名称。第一次尝试(可能有大量语法错误和其他错误,但程序的语义应该“更清晰”):

declare function local:reachable($country as element())
as (return value should be a sequence of countries )
{
if $country == () (:if empty, it doesn't border to any other country:)
then ()

else(
$country/name UNION (for $bord in $country/border/@country return
local:reachable ($database/country/car_code = @bord ))
)
}

对该函数的调用:

local:reachable($database/country[@car_code = "F"])

与法国接壤的国家应该是:

  <border country="AND" length="60"/>
<border country="E" length="623"/>
<border country="D" length="451"/>
<border country="I" length="488"/>
<border country="CH" length="573"/>
<border country="B" length="620"/>
<border country="L" length="73"/>
<border country="MC" length="4.4"/>

但是我们还需要找到这些国家的接壤国家。最终输出应该是“F”,“AND”,“E”,“D”,“I”,“CH”,“B”,“L”,“MC”...,X,Y,Z, (以及与这些国家接壤的其他国家)。

  • 我知道 UNION 未定义,但还有其他我可以使用的吗?我只是想让它更清楚我想做什么

  • 除了语法错误之外,还有一个大问题是,如果“F”与“L”接壤,那么“L”将与“F”接壤,所以我的“函数”永远不会终止 - 我该如何处理那?

  • 我可以获得语法方面的帮助

  • 如果问题不清楚,请告诉我,以便我进一步澄清

最佳答案

开始之前

以下是对您的代码的一些评论:

  • $country as element() 定义一个必须包含的变量恰好是一个元素,因此它永远不能为空;使用 element()? 如果该元素是可选的,element()*(如果可以有任意数量)它们,或者 element()+(如果必须有一个或多个)

  • 序列运算符,可用于构造序列其他序列: (1,2) , (3,4) 构造 2 个序列: (1,2) (3,4),然后构造另一个包含其他,结果为:(1,2,3,4)

数据

让我稍微改变一下countries元素,这样我就可以消除噪音,并使这个演示变得更简单一些。另外,我创建了一个简单但完整的 map 。假设我们有 2 个相邻国家 U和 K,以及另外 4 个形成一个正方形(每个国家都与 2 个国家相邻)其他):N、G、B 和 F。与现有地理或环境的任何相似之处政治只在你的眼里:-)

<!--
Map: U K | N G
B F
-->
<countries>
<country id="U">
<name>Over the top</name>
<border idref="K"/>
</country>
<country id="K">
<name>Beyond the see</name>
<border idref="U"/>
</country>
<country id="N">
<name>Flatland</name>
<border idref="B"/>
<border idref="G"/>
</country>
<country id="G">
<name>Marxhome</name>
<border idref="N"/>
<border idref="F"/>
</country>
<country id="B">
<name>Beerium</name>
<border idref="N"/>
<border idref="F"/>
</country>
<country id="F">
<name>Grapeandcheese</name>
<border idref="B"/>
<border idref="G"/>
</country>
</countries>

解决方案

该解决方案包括一个递归函数,该函数消耗一个队列国家来处理。同时,将结果列表累加1一时的国家。它需要队列中的第一个国家,将其添加到结果,然后递归到所有不相邻的国家已经在队列中或当前结果中。增广结果为也流传了下来。

xquery version "3.0";

declare variable $countries :=
<countries>
<!-- as above, just copy and paste it -->
</countries>;

declare function local:reachable(
$queue as element(country)*,
$result as element(country)*
) as element(country)*
{
if ( empty($queue) ) then (
(: we do not consider one country reachable from itself :)
tail($result)
)
else (
let $this := head($queue)
let $rest := tail($queue)
let $more := $this/border/@idref[not(. = ($queue, $result)/@id)]
return
local:reachable(
( $rest, $countries/country[@id = $more] ),
( $result, $this ))
)
};

(: for each countries, display its reachable countries
:)
for $c in $countries/country
order by $c/@id
let $r := local:reachable($c, ())
return
$c/name || ': ' || string-join($r/@id, ', ')

结果

Beerium: N, G, F
Grapeandcheese: N, G, B
Marxhome: N, B, F
Beyond the see: U
Flatland: G, B, F
Over the top: K

关于xquery - 使用 XQuery 进行递归的示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42949151/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com