Skip to content

Commit

Permalink
Fix arrax mode/majority confusion
Browse files Browse the repository at this point in the history
  • Loading branch information
domi4484 committed Feb 4, 2021
1 parent ab39dad commit 7345c12
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 19 deletions.
9 changes: 5 additions & 4 deletions resources/function_help/json/array_majority
Expand Up @@ -2,10 +2,11 @@
"name": "array_majority",
"type": "function",
"groups": ["Arrays"],
"description": "Returns an array containing the most common value in an array. The returned array may contain more than one value if multiple values occur equally often.",
"description": "Returns the value which has majority in the array. Majority means the count of the value is greather than half the size of the array.",
"arguments": [ {"arg":"array","description":"an array"} ],
"examples": [
{ "expression":"array_majority(array(0,1,42,42,43))", "returns":"[ 42 ]"},
{ "expression":"array_majority(array(0,0,1,2,2,42))", "returns":"[ 0, 2 ]"}
"examples": [
{ "expression":"array_majority(array(0,1,42,42,43))", "returns":"NULL"},
{ "expression":"array_majority(array(0,1,42,42,43,42))", "returns":"NULL"},
{ "expression":"array_majority(array(0,1,42,42,43,42,42))", "returns":"42"}
]
}
12 changes: 12 additions & 0 deletions resources/function_help/json/array_minority
@@ -0,0 +1,12 @@
{
"name": "array_minority",
"type": "function",
"groups": ["Arrays"],
"description": "Returns an array containing the minority values in an array. All values are minority exept the majority value if available.",
"arguments": [ {"arg":"array","description":"an array"} ],
"examples": [
{ "expression":"array_minority(array(0,1,42,42,43))", "returns":"[ 0, 1, 42, 43 ]"},
{ "expression":"array_minority(array(0,1,42,42,43,42))", "returns":"[ 0, 1, 42, 43 ]"},
{ "expression":"array_minority(array(0,1,42,42,43,42,42))", "returns":"[ 0, 1, 43 ]"}
]
}
11 changes: 11 additions & 0 deletions resources/function_help/json/array_mode
@@ -0,0 +1,11 @@
{
"name": "array_mode",
"type": "function",
"groups": ["Arrays"],
"description": "Returns an array containing the most common value in an array. The returned array may contain more than one value if multiple values occur equally often.",
"arguments": [ {"arg":"array","description":"an array"} ],
"examples": [
{ "expression":"array_mode(array(0,1,42,42,43))", "returns":"[ 42 ]"},
{ "expression":"array_mode(array(0,0,1,2,2,42))", "returns":"[ 0, 2 ]"}
]
}
73 changes: 60 additions & 13 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -5411,19 +5411,6 @@ static QVariant fcnArrayMedian( const QVariantList &values, const QgsExpressionC
}
}

static QVariant fcnArrayMajority( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
QHash< QVariant, int > hash;
for ( const auto &item : list )
{
++hash[item];
}
const QList< int > occurrences = hash.values();
const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
return list.isEmpty() ? QVariant() : hash.keys( maxValue );
}

static QVariant fcnArraySum( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
Expand Down Expand Up @@ -5454,6 +5441,64 @@ static QVariant convertToSameType( const QVariant &value, QVariant::Type type )
return result;
}

static QVariant fcnArrayMode( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
QHash< QVariant, int > hash;
for ( const auto &item : list )
{
++hash[item];
}
const QList< int > occurrences = hash.values();
const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
return convertToSameType( list.isEmpty() ? QVariant() : hash.keys( maxValue ), values.at( 0 ).type() );
}

static QVariant fcnArrayMajority( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
QHash< QVariant, int > hash;
for ( const auto &item : list )
{
++hash[item];
}
const QList< int > occurrences = hash.values();
const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );

QList< QVariant > keysMaxValue = hash.keys( maxValue );

if ( keysMaxValue.size() != 1 )
return QVariant();

if ( hash.value( keysMaxValue.first() ) * 2 <= list.size() )
return QVariant();

return keysMaxValue.first();
}

static QVariant fcnArrayMinority( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
QHash< QVariant, int > hash;
for ( const auto &item : list )
{
++hash[item];
}
const QList< int > occurrences = hash.values();
const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );

QList< QVariant > keysMaxValue = hash.keys( maxValue );

// Remove the majority, all others are minority
if ( keysMaxValue.size() == 1
&& hash.value( keysMaxValue.first() ) * 2 > list.size() )
{
hash.remove( keysMaxValue.first() );
}

return convertToSameType( hash.keys(), values.at( 0 ).type() );
}

static QVariant fcnArrayAppend( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
Expand Down Expand Up @@ -7056,7 +7101,9 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< new QgsStaticExpressionFunction( QStringLiteral( "array_max" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ), fcnArrayMaximum, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_mean" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ), fcnArrayMean, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_median" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ), fcnArrayMedian, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_mode" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ), fcnArrayMode, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_majority" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ), fcnArrayMajority, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_minority" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ), fcnArrayMinority, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_sum" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ), fcnArraySum, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_append" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), fcnArrayAppend, QStringLiteral( "Arrays" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "array_prepend" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), fcnArrayPrepend, QStringLiteral( "Arrays" ) )
Expand Down
19 changes: 17 additions & 2 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -1640,7 +1640,7 @@ class TestQgsExpression: public QObject
QTest::newRow( "array_last(array('a', 'b', 'c'))" ) << QStringLiteral( "array_last(array('a', 'b', 'c'))" ) << false << QVariant( "c" );
QTest::newRow( "array_last(array())" ) << QStringLiteral( "array_last(array())" ) << false << QVariant();

// array_min, array_max, array_mean, array_median, array_majority, array_sum
// array_min, array_max, array_mean, array_median,array_mode, array_majority, array_minority, array_sum
QTest::newRow( "array_min('forty two')" ) << QStringLiteral( "array_min('forty two')" ) << true << QVariant();
QTest::newRow( "array_min(42)" ) << QStringLiteral( "array_min(42)" ) << true << QVariant();
QTest::newRow( "array_min(array())" ) << QStringLiteral( "array_min(array())" ) << false << QVariant();
Expand All @@ -1661,10 +1661,25 @@ class TestQgsExpression: public QObject
QTest::newRow( "array_median(array())" ) << QStringLiteral( "array_median(array())" ) << false << QVariant();
QTest::newRow( "array_median(array(0,1,42,42,43))" ) << QStringLiteral( "array_median(array(0,1,42,42,43))" ) << false << QVariant( 42 );
QTest::newRow( "array_median(array(0,0,1,2,2,42,'a','b'))" ) << QStringLiteral( "array_median(array(0,0,1,2,2,42,'a','b'))" ) << false << QVariant( 1.5 );

QTest::newRow( "array_mode('forty two')" ) << QStringLiteral( "array_mode('forty two')" ) << true << QVariant();
QTest::newRow( "array_mode(42)" ) << QStringLiteral( "array_mode(42)" ) << true << QVariant();
QTest::newRow( "array_mode(array())" ) << QStringLiteral( "array_mode(array())" ) << false << QVariant();
QTest::newRow( "array_mode(array(1,2,42,42,'a','b'))" ) << QStringLiteral( "array_mode(array(1,2,42,42,'a','b'))" ) << false << QVariant( QVariantList() << 42 );

QTest::newRow( "array_majority('forty two')" ) << QStringLiteral( "array_majority('forty two')" ) << true << QVariant();
QTest::newRow( "array_majority(42)" ) << QStringLiteral( "array_majority(42)" ) << true << QVariant();
QTest::newRow( "array_majority(array())" ) << QStringLiteral( "array_majority(array())" ) << false << QVariant();
QTest::newRow( "array_majority(array(1,2,42,42,'a','b'))" ) << QStringLiteral( "array_majority(array(1,2,42,42,'a','b'))" ) << false << QVariant( QVariantList() << 42 );
QTest::newRow( "array_majority(array(0,1,42,42,43))" ) << QStringLiteral( "array_majority(array(0,1,42,42,43))" ) << false << QVariant();
QTest::newRow( "array_majority(array(0,1,42,42,43,42))" ) << QStringLiteral( "array_majority(array(0,1,42,42,43,42))" ) << false << QVariant();
QTest::newRow( "array_majority(array(0,1,42,42,43,42,42))" ) << QStringLiteral( "array_majority(array(0,1,42,42,43,42,42))" ) << false << QVariant( 42 );

QTest::newRow( "array_minority('forty two')" ) << QStringLiteral( "array_minority('forty two')" ) << true << QVariant();
QTest::newRow( "array_minority(42)" ) << QStringLiteral( "array_minority(42)" ) << true << QVariant();
QTest::newRow( "array_minority(array())" ) << QStringLiteral( "array_minority(array())" ) << false << QVariant( QVariantList() );
QTest::newRow( "array_minority(array(42,43))" ) << QStringLiteral( "array_minority(array(42,43))" ) << false << QVariant( QVariantList() << 42 << 43 );
QTest::newRow( "array_minority(array(42,43,42))" ) << QStringLiteral( "array_minority(array(42,43,42))" ) << false << QVariant( QVariantList() << 43 );

QTest::newRow( "array_sum('forty two')" ) << QStringLiteral( "array_sum('forty two')" ) << true << QVariant();
QTest::newRow( "array_sum(42)" ) << QStringLiteral( "array_sum(42)" ) << true << QVariant();
QTest::newRow( "array_sum(array())" ) << QStringLiteral( "array_sum(array())" ) << false << QVariant();
Expand Down

0 comments on commit 7345c12

Please sign in to comment.