Skip to content
Permalink
Browse files

[processing] Optimise uniqueValues method

Now it uses the standard QgsVectorLayer.uniqueValues() method
where possible so that provider side optimisations are used

Also add test, and optimise request when using selected
features only
  • Loading branch information
nyalldawson committed Oct 12, 2016
1 parent 05ea4be commit 6605a2274f84f7f90e846283f31eee8835018ad5
Showing with 42 additions and 6 deletions.
  1. +26 −0 python/plugins/processing/tests/ToolsTest.py
  2. +16 −6 python/plugins/processing/tools/vector.py
@@ -122,6 +122,32 @@ def testValues(self):

ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)

def testUniqueValues(self):
ProcessingConfig.initialize()

test_data = points2()
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')

# field by index
v = vector.uniqueValues(test_layer, 3)
self.assertEqual(len(v), len(set(v)))
self.assertEqual(set(v), set([2, 1, 0]))

# field by name
v = vector.uniqueValues(test_layer, 'id_2')
self.assertEqual(len(v), len(set(v)))
self.assertEqual(set(v), set([2, 1, 0]))

# test with selected features
previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
test_layer.selectByIds([2, 4, 6])
v = vector.uniqueValues(test_layer, 'id')
self.assertEqual(len(v), len(set(v)))
self.assertEqual(set(v), set([5, 7, 3]))

ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)


if __name__ == '__main__':
unittest.main()
@@ -122,13 +122,23 @@ def uniqueValues(layer, attribute):
Attribute can be defined using a field names or a zero-based
field index. It considers the existing selection.
"""
values = []

fieldIndex = resolveFieldIndex(layer, attribute)
feats = features(layer)
for feat in feats:
if feat.attributes()[fieldIndex] not in values:
values.append(feat.attributes()[fieldIndex])
return values
if ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED) \
and layer.selectedFeatureCount() > 0:

# iterate through selected features
values = []
request = QgsFeatureRequest().setSubsetOfAttributes([fieldIndex]).setFlags(QgsFeatureRequest.NoGeometry)
feats = features(layer, request)
for feat in feats:
if feat.attributes()[fieldIndex] not in values:
values.append(feat.attributes()[fieldIndex])
return values
else:
# no selection, or not considering selecting
# so we can take advantage of provider side unique value optimisations
return layer.uniqueValues(fieldIndex)


def resolveFieldIndex(layer, attr):

0 comments on commit 6605a22

Please sign in to comment.
You can’t perform that action at this time.