I found a code on my computer that i wrote a while ago. It is based on an exercise from O'Reilly book Programming the Semantic Web. There is a class, that stores RDF triples, that is data in the form subject-predicate-object:
class SimpleGraph:
def __init__(self):
self._spo = {}
self._pos = {}
self._osp = {}
def add(self, (s, p, o)):
# implementation details
pass
def remove(self, (s, p, o)):
# implementation details
pass
Variables _spo
, _pos
, _osp
are different permutations of subject, predicate, object for performance reasons, and the underlying data structure is dictionary of dictionaries of sets like {'subject': {'predicate': set([object])}}
or {'object': {'subject': set([predicate])}}
. The class also has a method to yield triples that match the query in a form of a tuple. If one element of a tuple is None, it acts as a wildcard.
def triples(self, (s, p, o)):
# check which terms are present
try:
if s != None:
if p != None:
# s p o
if o != None:
if o in self._spo[s][p]:
yield (s, p, o)
# s p _
else:
for ro in self._spo[s][p]:
yield (s, p, ro)
else:
# s _ o
if o != None:
for rp in self._osp[o][s]:
yield (s, rp, o)
# s _ _
else:
for rp, oset in self._spo[s].items():
for ro in oset:
yield (s, rp, ro)
else:
if p != None:
# _ p o
if o != None:
for rs in self._pos[p][o]:
yield (rs, p, o)
# _ p _
else:
for ro, sset in self._pos[p].items():
for rs in sset:
yield (rs, p, ro)
else:
# _ _ o
if o != None:
for rs, pset in self._osp[o].items():
for rp in pset:
yield (rs, rp, o)
# _ _ _
else:
for rs, pset in self._spo.items():
for rp, oset in pset.items():
for ro in oset:
yield (rs, rp, ro)
except KeyError:
pass
You see, this code is huge, and i feel it could be more terse and elegant. I suspect the possible use of dicts here, where tuple (s, p, o) is matched with a certain key in this dict, and then the yield is done. But i have no idea how to implement it.
How can i simplify this huge if-else structure?