Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>A Pure SPARQL 1.1 Solution</h2> <p>I've extended the data to make the problem a little harder. Let's add a duplicate element to the list, e.g., an additional <code>:a</code> at the end:</p> <pre><code>@prefix : &lt;http://example.org#&gt; . :ls :list (:a :b :c :a) . </code></pre> <p>Then we can use a query like this to extract each list node (and its element) along with the position of the node in the list. The idea is that we can match all the individual nodes in the list with a pattern like <code>[] :list/rdf:rest* ?node</code>. The <em>position</em> of each node, though, is the number of intermediate nodes between the head of the list and <code>?node</code>. We can match each of those intermediate nodes by breaking the pattern down into</p> <pre><code>[] :list/rdf:rest* ?mid . ?mid rdf:rest* :node . </code></pre> <p>Then if we group by <code>?node</code>, the number of distinct <code>?mid</code> bindings is the position of <code>?node</code> in the list. Thus we can use the following query (which also grabs the element (the <code>rdf:first</code>) associated with each node) to get the positions of elements in the list:</p> <pre class="lang-sql prettyprint-override"><code>prefix : &lt;https://stackoverflow.com/q/17523804/1281433/&gt; prefix rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt; select ?element (count(?mid)-1 as ?position) where { [] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node . ?node rdf:first ?element . } group by ?node ?element </code></pre> <pre><code>---------------------- | element | position | ====================== | :a | 0 | | :b | 1 | | :c | 2 | | :a | 3 | ---------------------- </code></pre> <p>This works because the structure of an RDF list is a linked list like this (where <code>?head</code> is the beginning of the list (the object of <code>:list</code>), and is another binding of <code>?mid</code> because of the pattern <code>[] :list/rdf:rest* ?mid</code>):</p> <p><img src="https://i.stack.imgur.com/MQJUT.png" alt="graphical representation of RDF list"></p> <h2>Comparison with Jena ARQ Extensions</h2> <p>The asker of the question also posted <a href="https://stackoverflow.com/a/17528290/1281433">an answer</a> that uses Jena's ARQ extensions for working with RDF lists. The solution posted in that answer is</p> <pre class="lang-sql prettyprint-override"><code>PREFIX : &lt;http://example.org#&gt; PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt; PREFIX list: &lt;http://jena.hpl.hp.com/ARQ/list#&gt; SELECT ?elem ?pos WHERE { ?x :list ?ls . ?ls list:index (?pos ?elem). } </code></pre> <p>This answer depends on using Jena's ARQ and enabling the extensions, but it is more concise and transparent. What isn't obvious is whether one has an obviously preferable performance. As it turns out, for small lists, the difference isn't particularly significant, but for larger lists, the ARQ extensions have <em>much</em> better performance. The runtime for the pure SPARQL query quickly becomes prohibitively long, while there's almost no difference in the version using the ARQ extensions.</p> <pre><code>------------------------------------------- | 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 | ------------------------------------------- </code></pre> <p>These specific values will obviously differ depending on your setup, but the general trend should be observable anywhere. Since things could change in the future, here's the particular version of ARQ I'm using:</p> <pre><code>$ 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 </code></pre> <p>As such, if I <em>knew</em> that I had to process lists of non-trivial sizes and that I had ARQ available, I'd use the extension.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload