xQuery-填充自定义数组

时间:2018-12-10 16:31:45

标签: xquery xquery-3.0

我得到了一些带有不同公司广告的数据集。

例如

<jobs>
    <job>
        <company>A</company>
        <value>Testvalue</value>
    </job>
    <job>
        <company>A</company>
        <value>Testvalue</value>
    </job>
    <job>
        <company>B</company>
        <value>Testvalue</value>
    </job>
    <job>
        <company>C</company>
        <value>Testvalue</value>
    </job>
</jobs>

我想做的是生成一个自定义输出。我希望每个公司只有1条记录

想要的示例输出:

<jobs>
    <job>
        <company>A</company>
        <value>Testvalue</value>
    </job>
    <job>
        <company>B</company>
        <value>Testvalue</value>
    </job>
    <job>
        <company>C</company>
        <value>Testvalue</value>
    </job>
</jobs>

我尝试的是以下内容:

如果公司不在数组中,请将其附加到数组中并将项目附加到另一个数组中。

(: loop through job in jobs :)
for $ad in //jobs/job
  (: firmenarray, "unique" ads :)
  let $companys := ()
  let $ads := ()
  (: declare company of ad:)
  let $company := $ad//company[1]
  (: if ad/company not within companyarray > add & concat to ads :)
  let $test := if(not(fn:index-of($companys, $company))) then(
    (: add ad/company to companys :)
    $companys = fn:insert-before($companys, 0, $company),
    (: add jobs/job to ads :)
    $ads = fn:insert-before($ads, 0, $ad)
  )
return $ads

不知何故,我一直在努力找出原因...

2 个答案:

答案 0 :(得分:4)

课本分组示例:

/**
@param {string|number[]}
*/

https://xqueryfiddle.liberty-development.net/b4GWVb

答案 1 :(得分:4)

Martin Honnen的group by解决方案是显而易见的也是最好的解决方案。但是,如果您想迭代地在XQuery中填充序列或数组,则必须了解您的方法在functional language之类的XQuery中不能工作,因为所有变量都是不可变的。如果您想超越简单的XPath和FLWOR表达式,那么了解函数式编程的基础非常重要。

函数式语言中迭代的“等效”是递归,因此这是使用用户定义的函数来递归解决您的任务的方法:

declare function local:unique($companies, $unique) {
  if(empty($companies)) then $unique
  else if($companies[1]/company = $unique/company)
  then local:unique(tail($companies), $unique)
  else local:unique(tail($companies), ($unique, $companies[1]))
};

<jobs>{
  local:unique(/jobs/job, ())
}</jobs>

这种遍历序列和汇总结果的特定模式非常普遍,以至于甚至被抽象为自己的标准函数fn:fold-left($sequence, $start-value, $aggregation-function)。有了它的帮助,解决方案变得很短:

<jobs>{
  fn:fold-left(/jobs/job, (), function($companies, $company) {
    if($company/company = $companies/company) then $companies
    else ($companies, $company)
  })
}</jobs>

但是由于您将每个新条目与所有先前找到的唯一公司条目进行比较,因此此输出仍然效率很低。实施得当的group by可能会永远胜过它。