Skip to content

Commit 6605a22

Browse files
committed
[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
1 parent 05ea4be commit 6605a22

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

python/plugins/processing/tests/ToolsTest.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,32 @@ def testValues(self):
122122

123123
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
124124

125+
def testUniqueValues(self):
126+
ProcessingConfig.initialize()
127+
128+
test_data = points2()
129+
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')
130+
131+
# field by index
132+
v = vector.uniqueValues(test_layer, 3)
133+
self.assertEqual(len(v), len(set(v)))
134+
self.assertEqual(set(v), set([2, 1, 0]))
135+
136+
# field by name
137+
v = vector.uniqueValues(test_layer, 'id_2')
138+
self.assertEqual(len(v), len(set(v)))
139+
self.assertEqual(set(v), set([2, 1, 0]))
140+
141+
# test with selected features
142+
previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
143+
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
144+
test_layer.selectByIds([2, 4, 6])
145+
v = vector.uniqueValues(test_layer, 'id')
146+
self.assertEqual(len(v), len(set(v)))
147+
self.assertEqual(set(v), set([5, 7, 3]))
148+
149+
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
150+
125151

126152
if __name__ == '__main__':
127153
unittest.main()

python/plugins/processing/tools/vector.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,23 @@ def uniqueValues(layer, attribute):
122122
Attribute can be defined using a field names or a zero-based
123123
field index. It considers the existing selection.
124124
"""
125-
values = []
125+
126126
fieldIndex = resolveFieldIndex(layer, attribute)
127-
feats = features(layer)
128-
for feat in feats:
129-
if feat.attributes()[fieldIndex] not in values:
130-
values.append(feat.attributes()[fieldIndex])
131-
return values
127+
if ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED) \
128+
and layer.selectedFeatureCount() > 0:
129+
130+
# iterate through selected features
131+
values = []
132+
request = QgsFeatureRequest().setSubsetOfAttributes([fieldIndex]).setFlags(QgsFeatureRequest.NoGeometry)
133+
feats = features(layer, request)
134+
for feat in feats:
135+
if feat.attributes()[fieldIndex] not in values:
136+
values.append(feat.attributes()[fieldIndex])
137+
return values
138+
else:
139+
# no selection, or not considering selecting
140+
# so we can take advantage of provider side unique value optimisations
141+
return layer.uniqueValues(fieldIndex)
132142

133143

134144
def resolveFieldIndex(layer, attr):

0 commit comments

Comments
 (0)