Xml XSLT以偶数分布对相邻值进行分组
我希望将相邻的值均匀地分布到一组中,使每组的总数大于300但小于390。为了实现这一点,我意识到有时需要拆分这些值,以达到设定的组数 如果我从下面开始,我只需要5秒:Xml XSLT以偶数分布对相邻值进行分组,xml,xslt,Xml,Xslt,我希望将相邻的值均匀地分布到一组中,使每组的总数大于300但小于390。为了实现这一点,我意识到有时需要拆分这些值,以达到设定的组数 如果我从下面开始,我只需要5秒: <root> <entry>5</entry> <entry>90</entry> <entry>55</entry> <entry>145</entry> <entry>
<root>
<entry>5</entry>
<entry>90</entry>
<entry>55</entry>
<entry>145</entry>
<entry>90</entry>
<entry>105</entry>
<entry>270</entry>
<entry>150</entry>
<entry>145</entry>
<entry>135</entry>
<entry>140</entry>
<entry>145</entry>
<entry>155</entry>
<entry>130</entry>
<entry>125</entry>
</root>`
5.
90
55
145
90
105
270
150
145
135
140
145
155
130
125
`
我想以这样的方式结束:
<root>
<group total="380">
<entry>5</entry>
<entry>90</entry>
<entry>55</entry>
<entry>145</entry>
<entry>90</entry>
</group>
<group total="375">
<entry>105</entry>
<entry>270</entry>
</group>
<group total="390">
<entry>150</entry>
<entry>145</entry>
<entry split='yes'>105</split>
</group>
<group total="390">
<entry split='yes'>30</entry>
<entry>140</entry>
<entry>145</entry>
<entry split='yes'>75</entry>
</group>
<group total="335">
<entry split='yes'>80</entry>
<entry>130</entry>
<entry>125</entry>
</group>
</root>
<xsl:variable name="total" select="sum(//entry)">
<xsl:variable name="set-number" select="xs:integer(ceiling($total div 390))"/>
<xsl:variable name="count" select="floor($total) div $set-number)"/>
<xsl:for-each-group select="entry" group-ending-with="*[(position() mod $count) = 0]">
<group total="{sum(current-group())}">
<xsl:apply-templates select="current-group()"/>
</group>
</xsl:for-each-group>
5.
90
55
145
90
105
270
150
145
105
30
140
145
75
80
130
125
我得到的最接近的结果是这样的:
<root>
<group total="380">
<entry>5</entry>
<entry>90</entry>
<entry>55</entry>
<entry>145</entry>
<entry>90</entry>
</group>
<group total="375">
<entry>105</entry>
<entry>270</entry>
</group>
<group total="390">
<entry>150</entry>
<entry>145</entry>
<entry split='yes'>105</split>
</group>
<group total="390">
<entry split='yes'>30</entry>
<entry>140</entry>
<entry>145</entry>
<entry split='yes'>75</entry>
</group>
<group total="335">
<entry split='yes'>80</entry>
<entry>130</entry>
<entry>125</entry>
</group>
</root>
<xsl:variable name="total" select="sum(//entry)">
<xsl:variable name="set-number" select="xs:integer(ceiling($total div 390))"/>
<xsl:variable name="count" select="floor($total) div $set-number)"/>
<xsl:for-each-group select="entry" group-ending-with="*[(position() mod $count) = 0]">
<group total="{sum(current-group())}">
<xsl:apply-templates select="current-group()"/>
</group>
</xsl:for-each-group>
这给了我:
<root>
<group total="150">
<entry>5</entry>
<entry>90</entry>
<entry>55</entry>
</group>
<group total="340">
<entry>145</entry>
<entry>90</entry>
<entry>105</entry>
</group>
<group total="565">
<entry>270</entry>
<entry>150</entry>
<entry>145</entry>
</group>
<group total="420">
<entry>135</entry>
<entry>140</entry>
<entry>145</entry>
</group>
<group total="410">
<entry>155</entry>
<entry>130</entry>
<entry>125</entry>
</group>
</root>
5.
90
55
145
90
105
270
150
145
135
140
145
155
130
125
这给了我正确的组数,但不是很均匀的分布 这可能是XSLT 3.0的工作
xsl:iterate
,尽管即使这样,我也很难一步处理、汇总和拆分输入数据
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes"
version="3.0">
<xsl:param name="min" as="xs:integer" select="300"/>
<xsl:param name="max" as="xs:integer" select="390"/>
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="root">
<xsl:copy>
<xsl:iterate select="entry">
<xsl:param name="total" as="xs:integer" select="0"/>
<xsl:param name="group" as="element(entry)*" select="()"/>
<xsl:on-completion>
<xsl:if test="$group">
<group>
<xsl:copy-of select="$group"/>
</group>
</xsl:if>
</xsl:on-completion>
<xsl:variable name="value" select="xs:integer(.)"/>
<xsl:variable name="sum" as="xs:integer" select="$total + $value"/>
<xsl:variable name="split" select="$sum gt $max and $total lt $min"/>
<xsl:variable name="splitted-values" as="element(entry)*">
<entry split="true">{$max - $total}</entry>
<entry split="true">{$sum - $max}</entry>
</xsl:variable>
<xsl:if test="$sum gt $max">
<group total="{$total + (if ($split) then $splitted-values[1][$split] else 0)}">
<xsl:copy-of select="$group, $splitted-values[1][$split]"/>
</group>
</xsl:if>
<xsl:next-iteration>
<xsl:with-param name="total" select="if ($sum > $max) then (if ($split) then $splitted-values[2] else xs:integer(.)) else $sum"/>
<xsl:with-param name="group"
select="if ($split and $sum gt $max)
then $splitted-values[2]
else if ($sum gt $max)
then .
else ($group, .)"/>
</xsl:next-iteration>
</xsl:iterate>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这很有魅力。是的,我的计算失败了(部分原因是我想让电脑代替我做这件事)。非常感谢您——我还没有对XSLT3.0进行过很多探索,但我肯定会在将来对它进行更多的研究!