假设我有一个列表100字符串元素和我想获得50这些随机文本字符串随机返回。XQuery从列表中获取随机文本
我尝试这样做:
let $list := ("a","b",..."element number 100")
return xdmp:random(100)
该查询返回一个字符串,我想回到50回字符串彼此不同。
假设我有一个列表100字符串元素和我想获得50这些随机文本字符串随机返回。XQuery从列表中获取随机文本
我尝试这样做:
let $list := ("a","b",..."element number 100")
return xdmp:random(100)
该查询返回一个字符串,我想回到50回字符串彼此不同。
最简单通过xdmp:random()
和限制命令到第一50:
(for $x in (1 to 100)
order by xdmp:random()
return $x
)[1 to 50]
假设它在每次调用返回不同的结果(但我不能从xdmp:random
的文件是否是这样说),下面的代码返回从列表中50串随机选出(但不一定是不同的):
let $list := ("a","b",..."element number 100")
for $i in 1 to 50
let $position = 1 + xdmp:random(99)
return $list[$position]
然而,xdmp:random
确切行为,即,它是否在调用返回相同的结果,依赖于发动机MarkLogic如何支持或治疗非确定性的行为,这是XQuery规范的范围之外。严格遵守规范实际上会返回50倍与上述查询相同的结果。
XQuery 3.1提供了一个可以控制种子的random number generator。这允许您通过链接调用来生成尽可能多的数字,而只使用可互操作的行为并保持在完全确定的领域。
编辑:这里是一个查询(仍然假设每次调用xdmp:random
)应该确保从grtjn的评论中得到列表中的50个不同的字符串。它使用GROUP BY子句,并依赖于一个懒惰的评价以最初的50
let $list := ("a","b",..."element number 100")
let $positions := (
for $i in 1 to 100000 (: can be adjusted to make sure we get 50 distinct :)
group by $position = 1 + xdmp:random(count($list) - 1)
return $position
)[position() le 50]
return $list[position() = $positions]
我觉得hunterhacker的提案计算$positions
是更好不过。
'xdmp:随机(N)'返回0至N,而位置1索引。你需要像'xdmp:random(99)+ 1' – BenW
啊是的,这是一个很好的观点!在XQuery中从0开始有点不同寻常。我已经相应地修正了。 –
如果您要说50个字符串必须与另一个不同,那么即使xdmp:random()在同一个查询中重复调用时返回不同的值,同样的名单是不够的,因为可能会有重复。你需要从50个不同的名单中获得随机头寸。
declare function local:pickSomeFromList($some as xs:integer, $listIn as xs:string*, $listOut as xs:string*) as xs:string* {
if($some = 0 or not($listIn)) then $listOut
else
let $random := xdmp:random(count($listIn) - 1) + 1
return local:pickSomeFromList(
$some - 1,
($listIn[fn:position() lt $random],$listIn[fn:position() gt $random]),
($listOut, $listIn[$random])
)
};
let $list := ("a","b","c","d","e","f","g","h","i","element number 10")
return local:pickSomeFromList(5, $list,())
xdmp:random()
(以及xdmp:elapsed-time()
)在每次调用返回不同的值。如果不行的话,这将是相当不切实际的。这与例如fn:current-dateTime()
相反,它在整个执行过程中给出相同的值。
Ghislain正在做一次很好的第一次尝试,但BenW也指出,即使xdmp:random()
每次都会返回不同的结果,但并不是说它们在整个执行过程中都是唯一的。它的64位最大比例的碰撞很少见(尽管仍然有可能),但在10或100之类的小尺度上,它可能会有一些意外的重复。一旦选择,从列表中删除文本是明智的。
BenW打败了我发布替代Ghislain,它看起来相似,但使用较少的行。无论如何,希望有人发现它有用:
declare function local:getRandomTexts($list, $count) {
if ($count > 0 and exists($list)) then
let $random := xdmp:random(count($list) - 1) + 1
let $text := $list[$random]
return ($text, local:getRandomTexts($list[. != $text], $count - 1))
else()
};
let $list :=
for $i in (1 to 26)
return fn:codepoints-to-string(64 + $i)
for $t in local:getRandomTexts($list, 100)
order by $t
return $t
HTH!
为任何人奇迹[“为什么不只是做$ list [xdmp:random(count($ list) - 1)+ 1]”](http://blog.davidcassel.net/2010/07/gotcha - 次序指数评价/)? –
这是一个很好的做法。 –