Skip to content

Commit 05ea4be

Browse files
committedOct 12, 2016
[processing] Fix inefficient values() method
Method was iterating over ever feature in a layer, including geometries and all attributes for EVERY attribute requested Add test and refactor so only one optimised iteration (eg no geometry, only required attributes) is used
1 parent 2665eb5 commit 05ea4be

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed
 

‎python/plugins/processing/tests/ToolsTest.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,44 @@ def testFeatures(self):
8484

8585
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
8686

87+
def testValues(self):
88+
ProcessingConfig.initialize()
89+
90+
test_data = points2()
91+
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')
92+
93+
# field by index
94+
res = vector.values(test_layer, 0)
95+
self.assertEqual(res[0], [1, 2, 3, 4, 5, 6, 7, 8])
96+
97+
# field by name
98+
res = vector.values(test_layer, 'id')
99+
self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8])
100+
101+
# two fields
102+
res = vector.values(test_layer, 0, 3)
103+
self.assertEqual(res[0], [1, 2, 3, 4, 5, 6, 7, 8])
104+
self.assertEqual(res[3], [2, 1, 0, 2, 1, 0, 0, 0])
105+
106+
# two fields by name
107+
res = vector.values(test_layer, 'id', 'id_2')
108+
self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8])
109+
self.assertEqual(res['id_2'], [2, 1, 0, 2, 1, 0, 0, 0])
110+
111+
# two fields by name and index
112+
res = vector.values(test_layer, 'id', 3)
113+
self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8])
114+
self.assertEqual(res[3], [2, 1, 0, 2, 1, 0, 0, 0])
115+
116+
# test with selected features
117+
previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
118+
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
119+
test_layer.selectByIds([2, 4, 6])
120+
res = vector.values(test_layer, 0)
121+
self.assertEqual(set(res[0]), set([5, 7, 3]))
122+
123+
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
124+
87125

88126
if __name__ == '__main__':
89127
unittest.main()

‎python/plugins/processing/tools/vector.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,30 @@ def values(layer, *attributes):
163163
to a number.
164164
"""
165165
ret = {}
166+
indices = []
167+
attr_keys = {}
166168
for attr in attributes:
167169
index = resolveFieldIndex(layer, attr)
168-
values = []
169-
feats = features(layer)
170-
for feature in feats:
170+
indices.append(index)
171+
attr_keys[index] = attr
172+
173+
# use an optimised feature request
174+
request = QgsFeatureRequest().setSubsetOfAttributes(indices).setFlags(QgsFeatureRequest.NoGeometry)
175+
176+
for feature in features(layer, request):
177+
for i in indices:
178+
179+
# convert attribute value to number
171180
try:
172-
v = float(feature.attributes()[index])
173-
values.append(v)
181+
v = float(feature.attributes()[i])
174182
except:
175-
values.append(None)
176-
ret[attr] = values
183+
v = None
184+
185+
k = attr_keys[i]
186+
if k in ret:
187+
ret[k].append(v)
188+
else:
189+
ret[k] = [v]
177190
return ret
178191

179192

1 commit comments

Comments
 (1)

nirvn commented on Oct 12, 2016

@nirvn
Contributor

Yay.

Please sign in to comment.