diff options
author | Gunnar Aastrand Grimnes <gromgull@users.noreply.github.com> | 2017-01-19 15:42:21 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-19 15:42:21 +0100 |
commit | 89c49f673e87bbf63d024ddd39b5e04cda460a6a (patch) | |
tree | 4834a51bfdfff04307e5e9921ca649140d3b5d2c | |
parent | 9e4bc5fee3b4bedf641b54a8fe461b2b228f768a (diff) | |
parent | 4e96763f67de0d03381c560da2fc1a39ac9c44ae (diff) | |
download | rdflib-89c49f673e87bbf63d024ddd39b5e04cda460a6a.tar.gz |
Merge pull request #691 from RDFLib/fix_609
Added __iadd__ method to collections, much faster for adding multiple…
-rw-r--r-- | rdflib/collection.py | 62 | ||||
-rw-r--r-- | rdflib/graph.py | 23 | ||||
-rw-r--r-- | test/test_issue223.py | 4 |
3 files changed, 64 insertions, 25 deletions
diff --git a/rdflib/collection.py b/rdflib/collection.py index 4fc3d1c8..babd4724 100644 --- a/rdflib/collection.py +++ b/rdflib/collection.py @@ -1,7 +1,6 @@ from rdflib.namespace import RDF from rdflib.term import BNode from rdflib.term import Literal -from rdflib.graph import Graph from rdflib.py3compat import format_doctest_out __all__ = ['Collection'] @@ -43,8 +42,7 @@ class Collection(object): def __init__(self, graph, uri, seq=[]): self.graph = graph self.uri = uri or BNode() - for item in seq: - self.append(item) + self += seq def n3(self): """ @@ -184,6 +182,16 @@ class Collection(object): """Iterator over items in Collections""" return self.graph.items(self.uri) + def _end(self): + # find end of list + container = self.uri + while True: + rest = self.graph.value(container, RDF.rest) + if rest == None or rest == RDF.nil: + return container + else: + container = rest + def append(self, item): """ >>> from rdflib.graph import Graph @@ -192,29 +200,36 @@ class Collection(object): >>> c = Collection(g,listName,[Literal(1),Literal(2)]) >>> links = [ ... list(g.subjects(object=i, predicate=RDF.first))[0] for i in c] - >>> len([i for i in links if (i,RDF.rest, RDF.nil) in g]) + >>> len([i for i in links if (i, RDF.rest, RDF.nil) in g]) 1 """ - container = self.uri - graph = self.graph - # iterate to the end of the linked list - rest = graph.value(container, RDF.rest) - while rest: - if rest == RDF.nil: - # the end, append to the end of the linked list - node = BNode() - graph.set((container, RDF.rest, node)) - container = node - break - else: - # move down one link - if container != self.uri: - rest = graph.value(rest, RDF.rest) - if not rest == RDF.nil: - container = rest - graph.add((container, RDF.first, item)) - graph.add((container, RDF.rest, RDF.nil)) + + end = self._end() + if (end, RDF.first, None) in self.graph: + # append new node to the end of the linked list + node = BNode() + self.graph.set((end, RDF.rest, node)) + end = node + + self.graph.add((end, RDF.first, item)) + self.graph.add((end, RDF.rest, RDF.nil)) + + def __iadd__(self, other): + + end = self._end() + self.graph.remove((end, RDF.rest, None)) + + for item in other: + if (end, RDF.first, None) in self.graph: + nxt = BNode() + self.graph.add((end, RDF.rest, nxt)) + end = nxt + + self.graph.add((end, RDF.first, item)) + + + self.graph.add((end, RDF.rest, RDF.nil)) def clear(self): container = self.uri @@ -233,6 +248,7 @@ def test(): if __name__ == "__main__": test() + from rdflib import Graph g = Graph() c = Collection(g, BNode()) diff --git a/rdflib/graph.py b/rdflib/graph.py index 012f63e6..bcfabd87 100644 --- a/rdflib/graph.py +++ b/rdflib/graph.py @@ -266,6 +266,7 @@ from rdflib.parser import Parser from rdflib.parser import create_input_source from rdflib.namespace import NamespaceManager from rdflib.resource import Resource +from rdflib.collection import Collection from rdflib import py3compat b = py3compat.b @@ -1177,6 +1178,28 @@ class Graph(Node): res.update(self.subjects()) return res + def collection(self, identifier): + """Create a new ``Collection`` instance. + + Parameters: + + - ``identifier``: a URIRef or BNode instance. + + Example:: + + >>> graph = Graph() + >>> uri = URIRef("http://example.org/resource") + >>> collection = graph.collection(uri) + >>> assert isinstance(collection, Collection) + >>> assert collection.uri is uri + >>> assert collection.graph is graph + >>> collection += [ Literal(1), Literal(2) ] + """ + + return Collection(self, identifier) + + + def resource(self, identifier): """Create a new ``Resource`` instance. diff --git a/test/test_issue223.py b/test/test_issue223.py index 5b1761ea..c12f4fa1 100644 --- a/test/test_issue223.py +++ b/test/test_issue223.py @@ -11,9 +11,9 @@ def test_collection_with_duplicates(): g = Graph().parse(data=ttl, format="turtle") for _,_,o in g.triples((URIRef("http://example.org/s"), URIRef("http://example.org/p"), None)): break - c = Collection(g, o) + c = g.collection(o) assert list(c) == list(URIRef("http://example.org/" + x) for x in ["a", "b", "a"]) assert len(c) == 3 - + if __name__ == '__main__': test_collection_with_duplicates() |