Add method to convert string to aggregate type

This commit is contained in:
Nyall Dawson 2016-05-16 15:00:55 +10:00
parent dcc047af49
commit 821134ca91
4 changed files with 96 additions and 0 deletions

View File

@ -70,5 +70,11 @@ class QgsAggregateCalculator
QVariant calculate( Aggregate aggregate, const QString& fieldOrExpression,
QgsExpressionContext* context = nullptr, bool* ok = nullptr ) const;
/** Converts a string to a aggregate type.
* @param string string to convert
* @param ok if specified, will be set to true if conversion was successful
* @returns aggregate type
*/
static Aggregate stringToAggregate( const QString& string, bool* ok = nullptr );
};

View File

@ -105,6 +105,56 @@ QVariant QgsAggregateCalculator::calculate( QgsAggregateCalculator::Aggregate ag
return calculate( aggregate, fit, resultType, attrNum, expression.data(), context, ok );
}
QgsAggregateCalculator::Aggregate QgsAggregateCalculator::stringToAggregate( const QString& string, bool* ok )
{
QString normalized = string.trimmed().toLower();
if ( ok )
*ok = true;
if ( normalized == "count" )
return Count;
else if ( normalized == "count_distinct" )
return CountDistinct;
else if ( normalized == "count_missing" )
return CountMissing;
else if ( normalized == "min" )
return Min;
else if ( normalized == "max" )
return Max;
else if ( normalized == "sum" )
return Sum;
else if ( normalized == "mean" )
return Mean;
else if ( normalized == "median" )
return Median;
else if ( normalized == "stdev" )
return StDev;
else if ( normalized == "stdevsample" )
return StDevSample;
else if ( normalized == "range" )
return Range;
else if ( normalized == "minority" )
return Minority;
else if ( normalized == "majority" )
return Majority;
else if ( normalized == "q1" )
return FirstQuartile;
else if ( normalized == "q3" )
return ThirdQuartile;
else if ( normalized == "iqr" )
return InterQuartileRange;
else if ( normalized == "min_length" )
return StringMinimumLength;
else if ( normalized == "max_length" )
return StringMaximumLength;
if ( ok )
*ok = false;
return Count;
}
QVariant QgsAggregateCalculator::calculate( QgsAggregateCalculator::Aggregate aggregate, QgsFeatureIterator& fit, QVariant::Type resultType,
int attr, QgsExpression* expression, QgsExpressionContext* context, bool* ok )
{

View File

@ -96,6 +96,13 @@ class CORE_EXPORT QgsAggregateCalculator
QVariant calculate( Aggregate aggregate, const QString& fieldOrExpression,
QgsExpressionContext* context = nullptr, bool* ok = nullptr ) const;
/** Converts a string to a aggregate type.
* @param string string to convert
* @param ok if specified, will be set to true if conversion was successful
* @returns aggregate type
*/
static Aggregate stringToAggregate( const QString& string, bool* ok = nullptr );
private:
//! Source layer

View File

@ -334,6 +334,39 @@ class TestQgsAggregateCalculator(unittest.TestCase):
self.assertTrue(ok)
self.assertEqual(val, 5)
def testStringToAggregate(self):
""" test converting strings to aggregate types """
tests = [[QgsAggregateCalculator.Count, ' cOUnT '],
[QgsAggregateCalculator.CountDistinct, ' count_distinct '],
[QgsAggregateCalculator.CountMissing, 'COUNT_MISSING'],
[QgsAggregateCalculator.Min, ' MiN'],
[QgsAggregateCalculator.Max, 'mAX'],
[QgsAggregateCalculator.Sum, 'sum'],
[QgsAggregateCalculator.Mean, 'MEAn '],
[QgsAggregateCalculator.Median, 'median'],
[QgsAggregateCalculator.StDev, 'stdev'],
[QgsAggregateCalculator.StDevSample, 'stdevsample'],
[QgsAggregateCalculator.Range, 'range'],
[QgsAggregateCalculator.Minority, 'minority'],
[QgsAggregateCalculator.Majority, 'majority'],
[QgsAggregateCalculator.FirstQuartile, 'q1'],
[QgsAggregateCalculator.ThirdQuartile, 'q3'],
[QgsAggregateCalculator.InterQuartileRange, 'iqr'],
[QgsAggregateCalculator.StringMinimumLength, 'min_length'],
[QgsAggregateCalculator.StringMaximumLength, 'max_length']]
for t in tests:
agg, ok = QgsAggregateCalculator.stringToAggregate(t[1])
self.assertTrue(ok)
self.assertEqual(agg, t[0])
# test some bad values
agg, ok = QgsAggregateCalculator.stringToAggregate('')
self.assertFalse(ok)
agg, ok = QgsAggregateCalculator.stringToAggregate('bad')
self.assertFalse(ok)
if __name__ == "__main__":
unittest.main()