假设我有以下Turtle声明:

@prefix : <http://example.org#> .

:ls :list (:a :b :c)

有没有一种方法可以获取元素在集合中的位置?

例如,使用此查询:
PREFIX :     <http://example.org#>
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?elem WHERE {
 ?x :list ?ls .
 ?ls rdf:rest*/rdf:first ?elem .
}

我得到:
--------
| elem |
========
| :a   |
| :b   |
| :c   |
--------

但我想查询来获得:
--------------
| elem | pos |
==============
| :a   |  0  |
| :b   |  1  |
| :c   |  2  |
--------------

可能吗?

最佳答案

纯SPARQL 1.1解决方案

我扩展了数据,使问题更加棘手。让我们向列表中添加一个重复元素,例如,在末尾添加一个附加的:a:

@prefix : <http://example.org#> .

:ls :list (:a :b :c :a) .

然后,我们可以使用这样的查询来提取每个列表节点(及其元素)以及该节点在列表中的位置。这个想法是我们可以使用[] :list/rdf:rest* ?node这样的模式来匹配列表中的所有单个节点。但是,每个节点的位置是列表开头与?node之间的中间节点数。我们可以通过将模式分解为每个中间节点来进行匹配
[] :list/rdf:rest* ?mid . ?mid rdf:rest* :node .

然后,如果我们按?node分组,则不同的?mid绑定(bind)的数量就是?node在列表中的位置。因此,我们可以使用以下查询(它还会获取与每个节点关联的元素(rdf:first))来获取元素在列表中的位置:

prefix : <https://stackoverflow.com/q/17523804/1281433/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

select ?element (count(?mid)-1 as ?position) where {
  [] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node .
  ?node rdf:first ?element .
}
group by ?node ?element
----------------------
| element | position |
======================
| :a      | 0        |
| :b      | 1        |
| :c      | 2        |
| :a      | 3        |
----------------------

之所以可行,是因为RDF列表的结构是这样的链接列表(其中?head是列表的开头(:list的对象),并且是?mid的另一个绑定(bind),因为是[] :list/rdf:rest* ?mid模式):

与Jena ARQ扩展的比较

该问题的询问者还发布了an answer,该文件使用Jena的ARQ扩展来处理RDF列表。该答案中发布的解决方案是

PREFIX :     <http://example.org#>
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>

SELECT ?elem ?pos WHERE {
 ?x :list ?ls .
 ?ls list:index (?pos ?elem).
}

这个答案取决于使用耶拿(Jena)的ARQ并启用扩展,但它更加简洁和透明。尚不清楚的是,是否有明显更好的性能。事实证明,对于较小的列表,差异并不是特别明显,但是对于较大的列表,ARQ扩展的性能要好得多。纯SPARQL查询的运行时间很快变得非常长,而使用ARQ扩展的版本几乎没有区别。
-------------------------------------------
| num elements | pure SPARQL | list:index |
===========================================
|      50      |    1.1s     |    0.8s    |
|     100      |    1.5s     |    0.8s    |
|     150      |    2.5s     |    0.8s    |
|     200      |    4.8s     |    0.8s    |
|     250      |    9.7s     |    0.8s    |
-------------------------------------------

这些特定值显然会因您的设置而有所不同,但是总体趋势应该在任何地方都可以观察到。由于将来情况可能会发生变化,因此以下是我使用的特定版本的ARQ:
$ arq --version
Jena:       VERSION: 2.10.0
Jena:       BUILD_DATE: 2013-02-20T12:04:26+0000
ARQ:        VERSION: 2.10.0
ARQ:        BUILD_DATE: 2013-02-20T12:04:26+0000

这样,如果我知道必须处理非平凡大小的列表并且可以使用ARQ,则可以使用扩展名。

08-25 14:33