Skip to content

Commit e5a419a

Browse files
RinkeHoekstramielvds
authored andcommitted
Speed up of compare_values and has_value methods by several orders of magnitude.
1 parent 8187597 commit e5a419a

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

lib/pyld/jsonld.py

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,6 @@ def to_rdf(self, input_, options):
10471047
issuer = IdentifierIssuer('_:b')
10481048
node_map = {'@default': {}}
10491049
self._create_node_map(expanded, node_map, '@default', issuer)
1050-
10511050
# output RDF dataset
10521051
dataset = {}
10531052
for graph_name, graph in sorted(node_map.items()):
@@ -1148,15 +1147,21 @@ def has_value(subject, property, value):
11481147
"""
11491148
if JsonLdProcessor.has_property(subject, property):
11501149
val = subject[property]
1151-
is_list = _is_list(val)
1152-
if _is_array(val) or is_list:
1153-
if is_list:
1154-
val = val['@list']
1150+
# Avoid double checking if val is a list.
1151+
# If val is a list, then we treat is as an array (i.e. if value occurs in the list, has_value returns true)
1152+
# TODO: is this desirable behavior?
1153+
if _is_list(val):
1154+
val = val['@list']
1155+
1156+
if _is_array(val):
11551157
for v in val:
1156-
if JsonLdProcessor.compare_values(value, v):
1157-
return True
1158+
# Avoid in depth comparison if the types are not the same
1159+
if type(v) == type(value):
1160+
return JsonLdProcessor.compare_values(value, v)
11581161
# avoid matching the set of values with an array value parameter
1159-
elif not _is_array(value):
1162+
# TODO: this means that if `value` is an array, there will be no comparison at all and we default to False
1163+
# is this desirable behavior?
1164+
elif not _is_array(value) and type(val) == type(value):
11601165
return JsonLdProcessor.compare_values(value, val)
11611166
return False
11621167

@@ -1275,28 +1280,33 @@ def compare_values(v1, v2):
12751280
12761281
:return: True if v1 and v2 are considered equal, False if not.
12771282
"""
1278-
# 1. equal primitives
1279-
if not _is_object(v1) and not _is_object(v2) and v1 == v2:
1280-
if isinstance(v1, bool) or isinstance(v2, bool):
1281-
return type(v1) is type(v2)
1282-
return True
1283-
1284-
# 2. equal @values
1285-
if (_is_value(v1) and _is_value(v2) and
1286-
v1['@value'] == v2['@value'] and
1287-
v1.get('@type') == v2.get('@type') and
1288-
v1.get('@language') == v2.get('@language') and
1289-
v1.get('@index') == v2.get('@index')):
12901283

1291-
if isinstance(v1['@value'], bool) or isinstance(v2['@value'], bool):
1292-
return type(v1['@value']) is type(v2['@value'])
1284+
# 1. equal primitives (= equal anything)
1285+
# This should just be equality...
1286+
# The previous version also returned true if one of the value types was bool and they were equal
1287+
# but they should only be equal if the types correspond as well.
1288+
# If they are both objects and they are equal in all respects, then they *are* equal (even if they are not primitives)
1289+
if v1 == v2:
12931290
return True
12941291

12951292
# 3. equal @ids
1296-
if (_is_object(v1) and '@id' in v1 and
1297-
_is_object(v2) and '@id' in v2):
1298-
return v1['@id'] == v2['@id']
1293+
# equal @ids only compares on one key, and is therefore preferred to do
1294+
# so let's do that first, and then only if there's a key error (i.e. no '@id'), we assume it's a value comparison.
1295+
try:
1296+
# If v1 and v2 have the same @id, they are the same
1297+
v1['@id'] == v2['@id']
1298+
except KeyError:
1299+
# if key error, then it is indeed a dict, but a literal value, not an object.
1300+
try:
1301+
return v1['@value'] == v2['@value'] and v1.get('@type') == v2.get('@type') and v1.get('@language') == v2.get('@language') and v1.get('@index') == v2.get('@index')
1302+
except:
1303+
# It is a dictionary, but a regular JSON one, not a JSON-LD dictionary
1304+
return False
1305+
except:
1306+
# one of v1 and v2 is not a dictionary
1307+
return False
12991308

1309+
# The two values are not the same.
13001310
return False
13011311

13021312
@staticmethod

0 commit comments

Comments
 (0)