mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[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
This commit is contained in:
parent
2665eb50a6
commit
05ea4be7c3
@ -84,6 +84,44 @@ class VectorTest(unittest.TestCase):
|
||||
|
||||
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
|
||||
|
||||
def testValues(self):
|
||||
ProcessingConfig.initialize()
|
||||
|
||||
test_data = points2()
|
||||
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')
|
||||
|
||||
# field by index
|
||||
res = vector.values(test_layer, 0)
|
||||
self.assertEqual(res[0], [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
|
||||
# field by name
|
||||
res = vector.values(test_layer, 'id')
|
||||
self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
|
||||
# two fields
|
||||
res = vector.values(test_layer, 0, 3)
|
||||
self.assertEqual(res[0], [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
self.assertEqual(res[3], [2, 1, 0, 2, 1, 0, 0, 0])
|
||||
|
||||
# two fields by name
|
||||
res = vector.values(test_layer, 'id', 'id_2')
|
||||
self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
self.assertEqual(res['id_2'], [2, 1, 0, 2, 1, 0, 0, 0])
|
||||
|
||||
# two fields by name and index
|
||||
res = vector.values(test_layer, 'id', 3)
|
||||
self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
self.assertEqual(res[3], [2, 1, 0, 2, 1, 0, 0, 0])
|
||||
|
||||
# test with selected features
|
||||
previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
|
||||
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
|
||||
test_layer.selectByIds([2, 4, 6])
|
||||
res = vector.values(test_layer, 0)
|
||||
self.assertEqual(set(res[0]), set([5, 7, 3]))
|
||||
|
||||
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -163,17 +163,30 @@ def values(layer, *attributes):
|
||||
to a number.
|
||||
"""
|
||||
ret = {}
|
||||
indices = []
|
||||
attr_keys = {}
|
||||
for attr in attributes:
|
||||
index = resolveFieldIndex(layer, attr)
|
||||
values = []
|
||||
feats = features(layer)
|
||||
for feature in feats:
|
||||
indices.append(index)
|
||||
attr_keys[index] = attr
|
||||
|
||||
# use an optimised feature request
|
||||
request = QgsFeatureRequest().setSubsetOfAttributes(indices).setFlags(QgsFeatureRequest.NoGeometry)
|
||||
|
||||
for feature in features(layer, request):
|
||||
for i in indices:
|
||||
|
||||
# convert attribute value to number
|
||||
try:
|
||||
v = float(feature.attributes()[index])
|
||||
values.append(v)
|
||||
v = float(feature.attributes()[i])
|
||||
except:
|
||||
values.append(None)
|
||||
ret[attr] = values
|
||||
v = None
|
||||
|
||||
k = attr_keys[i]
|
||||
if k in ret:
|
||||
ret[k].append(v)
|
||||
else:
|
||||
ret[k] = [v]
|
||||
return ret
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user