You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT2+ 如何合并含任意匹配元素的分组并去除元素重复项

XSLT 连通分组合并的替代实现思路

你当前实现的是存在公共元素的分组合并+元素去重需求,本质是求集合的连通分量,你用的逐元素递归查找所有连通节点的思路是可行的,以下是几个更高效或适配不同场景的可替代实现思路:


思路1:迭代合并分组(递归层级更低,性能更优)

直接以初始g分组为单位进行合并,不需要逐元素递归查找,适合分组数量较少的场景:

<xsl:variable name="initial-groups" select="$in/g"/>
<xsl:function name="k2:merge-groups">
  <xsl:param name="remaining-groups"/>
  <!-- 取第一个组,匹配所有和它有公共元素的组 -->
  <xsl:variable name="first-group" select="$remaining-groups[1]"/>
  <xsl:variable name="merge-targets" select="$remaining-groups[i = $first-group/i]"/>
  <!-- 合并后去重的元素集合 -->
  <xsl:variable name="merged-items" select="distinct-values($merge-targets/i)"/>
  <!-- 剩余未参与合并的组 -->
  <xsl:variable name="rest-groups" select="$remaining-groups[not(i = $first-group/i)]"/>
  <xsl:sequence select="
    if (empty($rest-groups)) then
      <g>{for $item in $merged-items return <i>{$item}</i>}</g>
    else
      (<g>{for $item in $merged-items return <i>{$item}</i>}</g>, k2:merge-groups($rest-groups))
  "/>
</xsl:function>

<!-- 调用入口 -->
<xsl:template match="/">
  <out>
    <xsl:copy-of select="k2:merge-groups($initial-groups)"/>
  </out>
</xsl:template>

思路2:用Key优化查找,降低重复计算开销

你的原有实现中递归函数每次都会遍历所有g节点查找匹配元素,用key预建立元素到所属分组的映射,可以大幅减少重复查找的开销,适合数据量较大的场景:

<!-- 预定义映射:按i的数值查询所属的g节点 -->
<xsl:key name="item-to-group" match="g" use="i/number(.)"/>

<xsl:function name="k2:find-connected" as="node()*">
  <xsl:param name="current-items" as="node()*"/>
  <xsl:param name="processed-items" as="xs:integer*"/>
  <!-- 找到当前所有i对应的分组,取出未处理的关联元素 -->
  <xsl:variable name="related-items" select="key('item-to-group', $current-items/number(.))/i[not(number(.) = $processed-items)]/number(.)"/>
  <xsl:sequence select="
    if (empty($related-items)) then
      $current-items
    else
      k2:find-connected(($current-items, $related-items), ($processed-items, $related-items))
  "/>
</xsl:function>

思路3:XSLT 3.0 累加器实现(适配大文件流式处理)

如果你的输入数据量达到GB级,可以用XSLT3.0的流式累加器逐节点处理,不需要一次性加载所有节点到内存,避免内存溢出:

<xsl:mode streamable="yes" use-accumulators="connection-map"/>
<xsl:accumulator name="connection-map" as="map(xs:integer, xs:integer*)" initial-value="map{}">
  <!-- 逐g节点处理,自动维护连通映射关系 -->
  <xsl:accumulator-rule match="g" select="
    let $item-vals := ./i!number(.),
        $exist-keys := map:keys($value)[. = $item-vals],
        $connected-vals := distinct-values(($item-vals, for $k in $exist-keys return map:get($value, $k)))
    return
      map:put(map:remove($value, $exist-keys), head($connected-vals), $connected-vals)
  "/>
</xsl:accumulator>

内容的提问来源于stack exchange,提问作者ktwice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 12:06:03