简体   繁体   中英

Reversing a string in SPARQL

Is it possible to reverse a string in SPARQL, so, eg, "abc" becomes "cba". Alternatively, is it possible to sort based on strings in reverse.

I am particularly interested in a solution that would work on Wikidata Query Service .

Well, you asked whether it's possible , not whether it's practical ...

SELECT ?s (group_concat(?letter; separator='') AS ?r) {
  BIND ("abcdefghijkl" AS ?s)
  VALUES ?d1 { 0 1 2 3 4 5 6 7 8 9 }
  VALUES ?d2 { 0 1 2 3 4 5 6 7 8 9 }
  VALUES ?d3 { 0 1 2 3 4 5 6 7 8 9 }
  BIND (100 * ?d3 + 10 * ?d2 + ?d1 + 1 AS ?i)
  BIND (SUBSTR(?s, ?i, 1) AS ?letter)
}
GROUP BY ?s

Live link

The approach is similar to that in Finn's response, but it works for strings up to a length of 1000 characters. This would be used as a subquery within a larger query. Aggregates like group_concat don't guarantee a particular order, so this query relies on the implementation-dependent ordering used by Blazegraph, and may jumble up the string on a different implementation.

If the use case is sorting by the last characters of a string in reverse order, then this could be tweaked so that it's guaranteed to include the last n characters of the string.

There is no "reverse string" function in SPARQL 1.1 .

There is no ORDER BY modifier that delivers the ordering you're looking for.

Many if not most programming and scripting languages do have "reverse string" and "sort" methods, so I'd suggest investigating whether your (unnamed) development environment has such.

This pathological implementation apparently works (up to a certain string length, here 12) in Blazegraph/Wikidata Query Service:

SELECT ?s ?r {
  BIND("abcdefghijkl" AS ?s)
  BIND(CONCAT(SUBSTR(?s, 12, 1), SUBSTR(?s, 11, 1), SUBSTR(?s, 10, 1),
              SUBSTR(?s, 9, 1), SUBSTR(?s, 8, 1), SUBSTR(?s, 7, 1),
              SUBSTR(?s, 6, 1), SUBSTR(?s, 5, 1), SUBSTR(?s, 4, 1),
              SUBSTR(?s, 3, 1), SUBSTR(?s, 2, 1), SUBSTR(?s, 1, 1)) AS ?r)
}

Here's a query targeting Virtuoso that provides the desired solution, courtesy of a sub-query.

SELECT ?str (GROUP_CONCAT(?letter; separator="") AS ?reverse)
WHERE {
          {
              SELECT ?str ?charAt 
              WHERE {
                      VALUES ?str { "abcdefghijk" }
                      VALUES ?d1 { 0 1 2 3 4 5 6 7 8 9 10 }
                      BIND(STRLEN(?str) - ?d1 AS ?charAt)
                      FILTER(?charAt > 0)
                    }
           }

          BIND(SUBSTR(?str,?charAt,1) AS ?letter) 
     }

Live Query Results Page .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM