diff --git a/python/core/qgsdatetimestatisticalsummary.sip b/python/core/qgsdatetimestatisticalsummary.sip index 964482c6637..3bb9b947282 100644 --- a/python/core/qgsdatetimestatisticalsummary.sip +++ b/python/core/qgsdatetimestatisticalsummary.sip @@ -53,12 +53,33 @@ class QgsDateTimeStatisticalSummary */ void reset(); - /** Calculates summary statistics for a list of variants. Any non-string variants will be + /** Calculates summary statistics for a list of variants. Any non-datetime variants will be * ignored. * @param values list of variants + * @see addValue() */ void calculate( const QVariantList& values ); + /** Adds a single datetime to the statistics calculation. Calling this method + * allows datetimes to be added to the calculation one at a time. For large + * quantities of dates this may be more efficient then first adding all the + * variants to a list and calling calculate(). + * @param value datetime to add. Any non-datetime variants will be ignored. + * @note call reset() before adding the first datetime using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final value and before + * retrieving calculated statistics. + * @see calculate() + * @see finalize() + */ + void addValue( const QVariant& value ); + + /** Must be called after adding all datetimes with addValue() and before retrieving + * any calculated datetime statistics. + * @see addValue() + */ + void finalize(); + /** Returns the value of a specified statistic * @param stat statistic to return * @returns calculated value of statistic diff --git a/python/core/qgsstatisticalsummary.sip b/python/core/qgsstatisticalsummary.sip index bb7c6db8ecc..10b0670941c 100644 --- a/python/core/qgsstatisticalsummary.sip +++ b/python/core/qgsstatisticalsummary.sip @@ -69,6 +69,25 @@ class QgsStatisticalSummary */ void calculate( const QList& values ); + /** Adds a single value to the statistics calculation. Calling this method + * allows values to be added to the calculation one at a time. For large + * quantities of values this may be more efficient then first adding all the + * values to a list and calling calculate(). + * @param value value to add + * @note call reset() before adding the first value using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final value and before + * retrieving calculated statistics. + * @see calculate() + * @see finalize() + */ + void addValue( double value ); + + /** Must be called after adding all values with addValues() and before retrieving + * any calculated statistics. + * @see addValue() + */ + void finalize(); /** Returns the value of a specified statistic * @param stat statistic to return * @returns calculated value of statistic diff --git a/python/core/qgsstringstatisticalsummary.sip b/python/core/qgsstringstatisticalsummary.sip index 037cd5e1e47..80b2fe6a124 100644 --- a/python/core/qgsstringstatisticalsummary.sip +++ b/python/core/qgsstringstatisticalsummary.sip @@ -57,19 +57,56 @@ class QgsStringStatisticalSummary */ void reset(); - /** Calculates summary statistics for a list of strings. + /** Calculates summary statistics for an entire list of strings at once. * @param values list of strings * @see calculateFromVariants() + * @see addString() */ void calculate( const QStringList& values ); - /** Calculates summary statistics for a list of variants. Any non-string variants will be - * ignored. + /** Calculates summary statistics for an entire list of variants at once. Any + * non-string variants will be ignored. * @param values list of variants * @see calculate() + * @see addValue() */ void calculateFromVariants( const QVariantList& values ); + /** Adds a single string to the statistics calculation. Calling this method + * allows strings to be added to the calculation one at a time. For large + * quantities of strings this may be more efficient then first adding all the + * strings to a list and calling calculate(). + * @param string string to add + * @note call reset() before adding the first string using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final string and before + * retrieving calculated statistics. + * @see calculate() + * @see addValue() + * @see finalize() + */ + void addString( const QString& string ); + + /** Adds a single variant to the statistics calculation. Calling this method + * allows variants to be added to the calculation one at a time. For large + * quantities of variants this may be more efficient then first adding all the + * variants to a list and calling calculateFromVariants(). + * @param value variant to add + * @note call reset() before adding the first string using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final value and before + * retrieving calculated statistics. + * @see calculateFromVariants() + * @see finalize() + */ + void addValue( const QVariant& value ); + + /** Must be called after adding all strings with addString() and before retrieving + * any calculated string statistics. + * @see addString() + */ + void finalize(); + /** Returns the value of a specified statistic * @param stat statistic to return * @returns calculated value of statistic diff --git a/src/core/qgsdatetimestatisticalsummary.cpp b/src/core/qgsdatetimestatisticalsummary.cpp index 78253f447f4..00b00f72d31 100644 --- a/src/core/qgsdatetimestatisticalsummary.cpp +++ b/src/core/qgsdatetimestatisticalsummary.cpp @@ -49,18 +49,30 @@ void QgsDateTimeStatisticalSummary::calculate( const QVariantList& values ) Q_FOREACH ( const QVariant& variant, values ) { - if ( variant.type() == QVariant::DateTime ) - { - testDateTime( variant.toDateTime() ); - } - else if ( variant.type() == QVariant::Date ) - { - QDate date = variant.toDate(); - testDateTime( date.isValid() ? QDateTime( date, QTime( 0, 0, 0 ) ) - : QDateTime() ); - } - // QTime? + addValue( variant ); } + finalize(); +} + +void QgsDateTimeStatisticalSummary::addValue( const QVariant& value ) +{ + if ( value.type() == QVariant::DateTime ) + { + testDateTime( value.toDateTime() ); + } + else if ( value.type() == QVariant::Date ) + { + QDate date = value.toDate(); + testDateTime( date.isValid() ? QDateTime( date, QTime( 0, 0, 0 ) ) + : QDateTime() ); + } + // QTime? +} + +void QgsDateTimeStatisticalSummary::finalize() +{ + //nothing to do for now - this method has been added for forward compatibility + //if statistics are implemented which require a post-calculation step } void QgsDateTimeStatisticalSummary::testDateTime( const QDateTime& dateTime ) diff --git a/src/core/qgsdatetimestatisticalsummary.h b/src/core/qgsdatetimestatisticalsummary.h index d50dcab9841..ce787c7f9e1 100644 --- a/src/core/qgsdatetimestatisticalsummary.h +++ b/src/core/qgsdatetimestatisticalsummary.h @@ -79,12 +79,33 @@ class CORE_EXPORT QgsDateTimeStatisticalSummary */ void reset(); - /** Calculates summary statistics for a list of variants. Any non-string variants will be + /** Calculates summary statistics for a list of variants. Any non-datetime variants will be * ignored. * @param values list of variants + * @see addValue() */ void calculate( const QVariantList& values ); + /** Adds a single datetime to the statistics calculation. Calling this method + * allows datetimes to be added to the calculation one at a time. For large + * quantities of dates this may be more efficient then first adding all the + * variants to a list and calling calculate(). + * @param value datetime to add. Any non-datetime variants will be ignored. + * @note call reset() before adding the first datetime using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final value and before + * retrieving calculated statistics. + * @see calculate() + * @see finalize() + */ + void addValue( const QVariant& value ); + + /** Must be called after adding all datetimes with addValue() and before retrieving + * any calculated datetime statistics. + * @see addValue() + */ + void finalize(); + /** Returns the value of a specified statistic * @param stat statistic to return * @returns calculated value of statistic diff --git a/src/core/qgsstatisticalsummary.cpp b/src/core/qgsstatisticalsummary.cpp index 07366c9fdca..7b3c5f92582 100644 --- a/src/core/qgsstatisticalsummary.cpp +++ b/src/core/qgsstatisticalsummary.cpp @@ -51,6 +51,7 @@ void QgsStatisticalSummary::reset() mFirstQuartile = 0; mThirdQuartile = 0; mValueCount.clear(); + mValues.clear(); } /*************************************************************************** @@ -65,15 +66,30 @@ void QgsStatisticalSummary::calculate( const QList &values ) Q_FOREACH ( double value, values ) { - mCount++; - mSum += value; - mMin = qMin( mMin, value ); - mMax = qMax( mMax, value ); - - if ( mStatistics & QgsStatisticalSummary::Majority || mStatistics & QgsStatisticalSummary::Minority || mStatistics & QgsStatisticalSummary::Variety ) - mValueCount.insert( value, mValueCount.value( value, 0 ) + 1 ); + addValue( value ); } + finalize(); +} + +void QgsStatisticalSummary::addValue( double value ) +{ + mCount++; + mSum += value; + mMin = qMin( mMin, value ); + mMax = qMax( mMax, value ); + + if ( mStatistics & QgsStatisticalSummary::Majority || mStatistics & QgsStatisticalSummary::Minority || mStatistics & QgsStatisticalSummary::Variety ) + mValueCount.insert( value, mValueCount.value( value, 0 ) + 1 ); + + if ( mStatistics & QgsStatisticalSummary::StDev || mStatistics & QgsStatisticalSummary::StDevSample || + mStatistics & QgsStatisticalSummary::Median || mStatistics & QgsStatisticalSummary::FirstQuartile || + mStatistics & QgsStatisticalSummary::ThirdQuartile || mStatistics & QgsStatisticalSummary::InterQuartileRange ) + mValues << value; +} + +void QgsStatisticalSummary::finalize() +{ if ( mCount == 0 ) return; @@ -82,31 +98,29 @@ void QgsStatisticalSummary::calculate( const QList &values ) if ( mStatistics & QgsStatisticalSummary::StDev || mStatistics & QgsStatisticalSummary::StDevSample ) { double sumSquared = 0; - Q_FOREACH ( double value, values ) + Q_FOREACH ( double value, mValues ) { double diff = value - mMean; sumSquared += diff * diff; } - mStdev = qPow( sumSquared / values.count(), 0.5 ); - mSampleStdev = qPow( sumSquared / ( values.count() - 1 ), 0.5 ); + mStdev = qPow( sumSquared / mValues.count(), 0.5 ); + mSampleStdev = qPow( sumSquared / ( mValues.count() - 1 ), 0.5 ); } - QList sorted; if ( mStatistics & QgsStatisticalSummary::Median || mStatistics & QgsStatisticalSummary::FirstQuartile || mStatistics & QgsStatisticalSummary::ThirdQuartile || mStatistics & QgsStatisticalSummary::InterQuartileRange ) { - sorted = values; - qSort( sorted.begin(), sorted.end() ); + qSort( mValues.begin(), mValues.end() ); bool even = ( mCount % 2 ) < 1; if ( even ) { - mMedian = ( sorted[mCount / 2 - 1] + sorted[mCount / 2] ) / 2.0; + mMedian = ( mValues[mCount / 2 - 1] + mValues[mCount / 2] ) / 2.0; } else //odd { - mMedian = sorted[( mCount + 1 ) / 2 - 1]; + mMedian = mValues[( mCount + 1 ) / 2 - 1]; } } @@ -119,11 +133,11 @@ void QgsStatisticalSummary::calculate( const QList &values ) bool even = ( halfCount % 2 ) < 1; if ( even ) { - mFirstQuartile = ( sorted[halfCount / 2 - 1] + sorted[halfCount / 2] ) / 2.0; + mFirstQuartile = ( mValues[halfCount / 2 - 1] + mValues[halfCount / 2] ) / 2.0; } else //odd { - mFirstQuartile = sorted[( halfCount + 1 ) / 2 - 1]; + mFirstQuartile = mValues[( halfCount + 1 ) / 2 - 1]; } } else @@ -132,11 +146,11 @@ void QgsStatisticalSummary::calculate( const QList &values ) bool even = ( halfCount % 2 ) < 1; if ( even ) { - mFirstQuartile = ( sorted[halfCount / 2 - 1] + sorted[halfCount / 2] ) / 2.0; + mFirstQuartile = ( mValues[halfCount / 2 - 1] + mValues[halfCount / 2] ) / 2.0; } else //odd { - mFirstQuartile = sorted[( halfCount + 1 ) / 2 - 1]; + mFirstQuartile = mValues[( halfCount + 1 ) / 2 - 1]; } } } @@ -150,11 +164,11 @@ void QgsStatisticalSummary::calculate( const QList &values ) bool even = ( halfCount % 2 ) < 1; if ( even ) { - mThirdQuartile = ( sorted[ halfCount + halfCount / 2 - 1] + sorted[ halfCount + halfCount / 2] ) / 2.0; + mThirdQuartile = ( mValues[ halfCount + halfCount / 2 - 1] + mValues[ halfCount + halfCount / 2] ) / 2.0; } else //odd { - mThirdQuartile = sorted[( halfCount + 1 ) / 2 - 1 + halfCount ]; + mThirdQuartile = mValues[( halfCount + 1 ) / 2 - 1 + halfCount ]; } } else @@ -163,11 +177,11 @@ void QgsStatisticalSummary::calculate( const QList &values ) bool even = ( halfCount % 2 ) < 1; if ( even ) { - mThirdQuartile = ( sorted[ halfCount + halfCount / 2 - 2 ] + sorted[ halfCount + halfCount / 2 - 1 ] ) / 2.0; + mThirdQuartile = ( mValues[ halfCount + halfCount / 2 - 2 ] + mValues[ halfCount + halfCount / 2 - 1 ] ) / 2.0; } else //odd { - mThirdQuartile = sorted[( halfCount + 1 ) / 2 - 2 + halfCount ]; + mThirdQuartile = mValues[( halfCount + 1 ) / 2 - 2 + halfCount ]; } } } diff --git a/src/core/qgsstatisticalsummary.h b/src/core/qgsstatisticalsummary.h index 12bb5717296..9f48b099a96 100644 --- a/src/core/qgsstatisticalsummary.h +++ b/src/core/qgsstatisticalsummary.h @@ -91,6 +91,26 @@ class CORE_EXPORT QgsStatisticalSummary */ void calculate( const QList& values ); + /** Adds a single value to the statistics calculation. Calling this method + * allows values to be added to the calculation one at a time. For large + * quantities of values this may be more efficient then first adding all the + * values to a list and calling calculate(). + * @param value value to add + * @note call reset() before adding the first value using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final value and before + * retrieving calculated statistics. + * @see calculate() + * @see finalize() + */ + void addValue( double value ); + + /** Must be called after adding all values with addValues() and before retrieving + * any calculated statistics. + * @see addValue() + */ + void finalize(); + /** Returns the value of a specified statistic * @param stat statistic to return * @returns calculated value of statistic @@ -201,6 +221,7 @@ class CORE_EXPORT QgsStatisticalSummary double mFirstQuartile; double mThirdQuartile; QMap< double, int > mValueCount; + QList< double > mValues; }; Q_DECLARE_OPERATORS_FOR_FLAGS( QgsStatisticalSummary::Statistics ) diff --git a/src/core/qgsstringstatisticalsummary.cpp b/src/core/qgsstringstatisticalsummary.cpp index 94b207c9dbe..3ee36e39ddf 100644 --- a/src/core/qgsstringstatisticalsummary.cpp +++ b/src/core/qgsstringstatisticalsummary.cpp @@ -52,6 +52,27 @@ void QgsStringStatisticalSummary::calculate( const QStringList& values ) { testString( string ); } + finalize(); +} + +void QgsStringStatisticalSummary::addString( const QString& string ) +{ + testString( string ); +} + +void QgsStringStatisticalSummary::addValue( const QVariant& value ) +{ + if ( value.type() == QVariant::String ) + { + testString( value.toString() ); + } + finalize(); +} + +void QgsStringStatisticalSummary::finalize() +{ + //nothing to do for now - this method has been added for forward compatibility + //if statistics are implemented which require a post-calculation step } void QgsStringStatisticalSummary::calculateFromVariants( const QVariantList& values ) diff --git a/src/core/qgsstringstatisticalsummary.h b/src/core/qgsstringstatisticalsummary.h index 73f5fcc372a..e78e7cd82d6 100644 --- a/src/core/qgsstringstatisticalsummary.h +++ b/src/core/qgsstringstatisticalsummary.h @@ -77,19 +77,56 @@ class CORE_EXPORT QgsStringStatisticalSummary */ void reset(); - /** Calculates summary statistics for a list of strings. + /** Calculates summary statistics for an entire list of strings at once. * @param values list of strings * @see calculateFromVariants() + * @see addString() */ void calculate( const QStringList& values ); - /** Calculates summary statistics for a list of variants. Any non-string variants will be - * ignored. + /** Calculates summary statistics for an entire list of variants at once. Any + * non-string variants will be ignored. * @param values list of variants * @see calculate() + * @see addValue() */ void calculateFromVariants( const QVariantList& values ); + /** Adds a single string to the statistics calculation. Calling this method + * allows strings to be added to the calculation one at a time. For large + * quantities of strings this may be more efficient then first adding all the + * strings to a list and calling calculate(). + * @param string string to add + * @note call reset() before adding the first string using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final string and before + * retrieving calculated statistics. + * @see calculate() + * @see addValue() + * @see finalize() + */ + void addString( const QString& string ); + + /** Adds a single variant to the statistics calculation. Calling this method + * allows variants to be added to the calculation one at a time. For large + * quantities of variants this may be more efficient then first adding all the + * variants to a list and calling calculateFromVariants(). + * @param value variant to add + * @note call reset() before adding the first string using this method + * to clear the results from any previous calculations + * @note finalize() must be called after adding the final value and before + * retrieving calculated statistics. + * @see calculateFromVariants() + * @see finalize() + */ + void addValue( const QVariant& value ); + + /** Must be called after adding all strings with addString() and before retrieving + * any calculated string statistics. + * @see addString() + */ + void finalize(); + /** Returns the value of a specified statistic * @param stat statistic to return * @returns calculated value of statistic diff --git a/tests/src/core/testqgsstatisticalsummary.cpp b/tests/src/core/testqgsstatisticalsummary.cpp index 7ab5d6f07db..29c4f0e233e 100644 --- a/tests/src/core/testqgsstatisticalsummary.cpp +++ b/tests/src/core/testqgsstatisticalsummary.cpp @@ -62,64 +62,147 @@ void TestQgsStatisticSummary::cleanup() void TestQgsStatisticSummary::stats() { + //note - we test everything twice, once using the statistics calculated by passing + //a list of values and once using the statistics calculated by passing values + //one-at-a-time QgsStatisticalSummary s( QgsStatisticalSummary::All ); + QgsStatisticalSummary s2( QgsStatisticalSummary::All ); QList values; values << 4 << 2 << 3 << 2 << 5 << 8; s.calculate( values ); + s2.addValue( 4 ); + s2.addValue( 2 ); + s2.addValue( 3 ); + s2.addValue( 2 ); + s2.addValue( 5 ); + s2.addValue( 8 ); + s2.finalize(); QCOMPARE( s.count(), 6 ); + QCOMPARE( s2.count(), 6 ); QCOMPARE( s.sum(), 24.0 ); + QCOMPARE( s2.sum(), 24.0 ); QCOMPARE( s.mean(), 4.0 ); + QCOMPARE( s2.mean(), 4.0 ); QVERIFY( qgsDoubleNear( s.stDev(), 2.0816, 0.0001 ) ); + QVERIFY( qgsDoubleNear( s2.stDev(), 2.0816, 0.0001 ) ); QVERIFY( qgsDoubleNear( s.sampleStDev(), 2.2803, 0.0001 ) ); + QVERIFY( qgsDoubleNear( s2.sampleStDev(), 2.2803, 0.0001 ) ); QCOMPARE( s.min(), 2.0 ); + QCOMPARE( s2.min(), 2.0 ); QCOMPARE( s.max(), 8.0 ); + QCOMPARE( s2.max(), 8.0 ); QCOMPARE( s.range(), 6.0 ); + QCOMPARE( s2.range(), 6.0 ); QCOMPARE( s.median(), 3.5 ); + QCOMPARE( s2.median(), 3.5 ); values << 9; s.calculate( values ); + s2.addValue( 9 ); + s2.finalize(); QCOMPARE( s.median(), 4.0 ); + QCOMPARE( s2.median(), 4.0 ); values << 4 << 5 << 8 << 12 << 12 << 12; s.calculate( values ); + s2.addValue( 4 ); + s2.addValue( 5 ) ; + s2.addValue( 8 ); + s2.addValue( 12 ); + s2.addValue( 12 ); + s2.addValue( 12 ); + s2.finalize(); QCOMPARE( s.variety(), 7 ); + QCOMPARE( s2.variety(), 7 ); QCOMPARE( s.minority(), 3.0 ); + QCOMPARE( s2.minority(), 3.0 ); QCOMPARE( s.majority(), 12.0 ); + QCOMPARE( s2.majority(), 12.0 ); //test quartiles. lots of possibilities here, involving odd/even/divisible by 4 counts values.clear(); values << 7 << 15 << 36 << 39 << 40 << 41; s.calculate( values ); + s2.reset(); + s2.addValue( 7 ); + s2.addValue( 15 ); + s2.addValue( 36 ); + s2.addValue( 39 ); + s2.addValue( 40 ); + s2.addValue( 41 ); + s2.finalize(); QCOMPARE( s.median(), 37.5 ); + QCOMPARE( s2.median(), 37.5 ); QCOMPARE( s.firstQuartile(), 15.0 ); + QCOMPARE( s2.firstQuartile(), 15.0 ); QCOMPARE( s.thirdQuartile(), 40.0 ); + QCOMPARE( s2.thirdQuartile(), 40.0 ); QCOMPARE( s.interQuartileRange(), 25.0 ); + QCOMPARE( s2.interQuartileRange(), 25.0 ); values.clear(); values << 7 << 15 << 36 << 39 << 40 << 41 << 43 << 49; s.calculate( values ); + s2.reset(); + s2.addValue( 7 ); + s2.addValue( 15 ); + s2.addValue( 36 ); + s2.addValue( 39 ); + s2.addValue( 40 ); + s2.addValue( 41 ) ; + s2.addValue( 43 ); + s2.addValue( 49 ); + s2.finalize(); QCOMPARE( s.median(), 39.5 ); + QCOMPARE( s2.median(), 39.5 ); QCOMPARE( s.firstQuartile(), 25.5 ); + QCOMPARE( s2.firstQuartile(), 25.5 ); QCOMPARE( s.thirdQuartile(), 42.0 ); + QCOMPARE( s2.thirdQuartile(), 42.0 ); QCOMPARE( s.interQuartileRange(), 16.5 ); + QCOMPARE( s2.interQuartileRange(), 16.5 ); values.clear(); values << 6 << 7 << 15 << 36 << 39 << 40 << 41 << 42 << 43 << 47 << 49; s.calculate( values ); + s2.reset(); + s2.addValue( 6 ); + s2.addValue( 7 ); + s2.addValue( 15 ); + s2.addValue( 36 ); + s2.addValue( 39 ); + s2.addValue( 40 ); + s2.addValue( 41 ); + s2.addValue( 42 ); + s2.addValue( 43 ); + s2.addValue( 47 ); + s2.addValue( 49 ); + s2.finalize(); QCOMPARE( s.median(), 40.0 ); + QCOMPARE( s2.median(), 40.0 ); QCOMPARE( s.firstQuartile(), 25.5 ); + QCOMPARE( s2.firstQuartile(), 25.5 ); QCOMPARE( s.thirdQuartile(), 42.5 ); + QCOMPARE( s2.thirdQuartile(), 42.5 ); QCOMPARE( s.interQuartileRange(), 17.0 ); + QCOMPARE( s2.interQuartileRange(), 17.0 ); values.clear(); values << 6 << 7 << 15 << 36 << 39 << 40 << 41 << 42 << 43 << 47 << 49 << 50 << 58; s.calculate( values ); + s2.addValue( 50 ); + s2.addValue( 58 ); + s2.finalize(); QCOMPARE( s.median(), 41.0 ); + QCOMPARE( s2.median(), 41.0 ); QCOMPARE( s.firstQuartile(), 36.0 ); + QCOMPARE( s2.firstQuartile(), 36.0 ); QCOMPARE( s.thirdQuartile(), 47.0 ); + QCOMPARE( s2.thirdQuartile(), 47.0 ); QCOMPARE( s.interQuartileRange(), 11.0 ); + QCOMPARE( s2.interQuartileRange(), 11.0 ); } void TestQgsStatisticSummary::individualStatCalculations_data() @@ -165,6 +248,22 @@ void TestQgsStatisticSummary::individualStatCalculations() s.calculate( values ); QVERIFY( qgsDoubleNear( s.statistic( stat ), expected, 0.00001 ) ); + //also test using values added one-at-a-time + QgsStatisticalSummary s2( QgsStatisticalSummary::Statistics( 0 ) ); + s2.setStatistics( stat ); + s2.addValue( 4 ); + s2.addValue( 4 ); + s2.addValue( 2 ); + s2.addValue( 3 ); + s2.addValue( 3 ); + s2.addValue( 3 ) ; + s2.addValue( 5 ) ; + s2.addValue( 5 ) ; + s2.addValue( 8 ); + s2.addValue( 8 ); + s2.finalize(); + QCOMPARE( s2.statistics(), stat ); + //make sure stat has a valid display name QVERIFY( !QgsStatisticalSummary::displayName( stat ).isEmpty() ); } diff --git a/tests/src/python/test_qgsdatetimestatisticalsummary.py b/tests/src/python/test_qgsdatetimestatisticalsummary.py index 732a5c1424f..a0cec1d61d9 100644 --- a/tests/src/python/test_qgsdatetimestatisticalsummary.py +++ b/tests/src/python/test_qgsdatetimestatisticalsummary.py @@ -24,19 +24,29 @@ from qgis.testing import unittest class PyQgsDateTimeStatisticalSummary(unittest.TestCase): def testStats(self): + # we test twice, once with values added as a list and once using values + # added one-at-a-time + + dates = [QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), + QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), + QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), + QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), + QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), + QDateTime(), + QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), + QDateTime(), + QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))] s = QgsDateTimeStatisticalSummary() self.assertEqual(s.statistics(), QgsDateTimeStatisticalSummary.All) - s.calculate([QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), - QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), - QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), - QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), - QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), - QDateTime(), - QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), - QDateTime(), - QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))]) + s.calculate(dates) + s2 = QgsDateTimeStatisticalSummary() + for d in dates: + s2.addValue(d) + s2.finalize() self.assertEqual(s.count(), 9) + self.assertEqual(s2.count(), 9) self.assertEqual(s.countDistinct(), 6) + self.assertEqual(s2.countDistinct(), 6) self.assertEqual(set(s.distinctValues()), set([QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), @@ -44,10 +54,15 @@ class PyQgsDateTimeStatisticalSummary(unittest.TestCase): QDateTime(), QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))])) + self.assertEqual(s2.distinctValues(), s.distinctValues()) self.assertEqual(s.countMissing(), 2) + self.assertEqual(s2.countMissing(), 2) self.assertEqual(s.min(), QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54))) + self.assertEqual(s2.min(), QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54))) self.assertEqual(s.max(), QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1))) + self.assertEqual(s2.max(), QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1))) self.assertEqual(s.range(), QgsInterval(693871147)) + self.assertEqual(s2.range(), QgsInterval(693871147)) def testIndividualStats(self): # tests calculation of statistics one at a time, to make sure statistic calculations are not @@ -60,7 +75,10 @@ class PyQgsDateTimeStatisticalSummary(unittest.TestCase): {'stat': QgsDateTimeStatisticalSummary.Range, 'expected': QgsInterval(693871147)}, ] + # we test twice, once with values added as a list and once using values + # added one-at-a-time s = QgsDateTimeStatisticalSummary() + s3 = QgsDateTimeStatisticalSummary() for t in tests: # test constructor s2 = QgsDateTimeStatisticalSummary(t['stat']) @@ -68,16 +86,25 @@ class PyQgsDateTimeStatisticalSummary(unittest.TestCase): s.setStatistics(t['stat']) self.assertEqual(s.statistics(), t['stat']) - s.calculate([QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), - QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), - QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), - QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), - QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), - QDateTime(), - QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), - QDateTime(), - QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))]) + s3.setStatistics(t['stat']) + + dates = [QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), + QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), + QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), + QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), + QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), + QDateTime(), + QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), + QDateTime(), + QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))] + s.calculate(dates) + s3.reset() + for d in dates: + s3.addValue(d) + s3.finalize() + self.assertEqual(s.statistic(t['stat']), t['expected']) + self.assertEqual(s3.statistic(t['stat']), t['expected']) # display name self.assertTrue(len(QgsDateTimeStatisticalSummary.displayName(t['stat'])) > 0) diff --git a/tests/src/python/test_qgsstringstatisticalsummary.py b/tests/src/python/test_qgsstringstatisticalsummary.py index 9ad1433d6d3..8d7984f32dc 100644 --- a/tests/src/python/test_qgsstringstatisticalsummary.py +++ b/tests/src/python/test_qgsstringstatisticalsummary.py @@ -22,17 +22,32 @@ from qgis.testing import unittest class PyQgsStringStatisticalSummary(unittest.TestCase): def testStats(self): + # we test twice, once with values added as a list and once using values + # added one-at-a-time s = QgsStringStatisticalSummary() self.assertEqual(s.statistics(), QgsStringStatisticalSummary.All) - s.calculate(['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd']) + strings = ['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd'] + s.calculate(strings) + s2 = QgsStringStatisticalSummary() + for string in strings: + s2.addString(string) + s2.finalize() self.assertEqual(s.count(), 9) + self.assertEqual(s2.count(), 9) self.assertEqual(s.countDistinct(), 6) + self.assertEqual(s2.countDistinct(), 6) self.assertEqual(set(s.distinctValues()), set(['cc', 'aaaa', 'bbbbbbbb', 'eeee', 'dddd', ''])) + self.assertEqual(s2.distinctValues(), s.distinctValues()) self.assertEqual(s.countMissing(), 2) + self.assertEqual(s2.countMissing(), 2) self.assertEqual(s.min(), 'aaaa') + self.assertEqual(s2.min(), 'aaaa') self.assertEqual(s.max(), 'eeee') + self.assertEqual(s2.max(), 'eeee') self.assertEqual(s.minLength(), 0) + self.assertEqual(s2.minLength(), 0) self.assertEqual(s.maxLength(), 8) + self.assertEqual(s2.maxLength(), 8) #extra check for minLength without empty strings s.calculate(['1111111', '111', '11111']) @@ -51,15 +66,25 @@ class PyQgsStringStatisticalSummary(unittest.TestCase): ] s = QgsStringStatisticalSummary() + s3 = QgsStringStatisticalSummary() for t in tests: # test constructor s2 = QgsStringStatisticalSummary(t['stat']) self.assertEqual(s2.statistics(), t['stat']) s.setStatistics(t['stat']) + s3.setStatistics(t['stat']) self.assertEqual(s.statistics(), t['stat']) - s.calculate(['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd']) + + strings = ['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd'] + s.calculate(strings) + s3.reset() + for string in strings: + s3.addString(string) + s3.finalize() + self.assertEqual(s.statistic(t['stat']), t['expected']) + self.assertEqual(s3.statistic(t['stat']), t['expected']) # display name self.assertTrue(len(QgsStringStatisticalSummary.displayName(t['stat'])) > 0)