mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
[FEATURE] add foreach expression for arrays
This commit is contained in:
parent
2d5499bfd1
commit
0a20621191
13
resources/function_help/json/array_foreach
Normal file
13
resources/function_help/json/array_foreach
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "array_foreach",
|
||||
"type": "function",
|
||||
"description": "Returns an array with the given expression evaluated on each item.",
|
||||
"arguments": [
|
||||
{"arg":"array","description":"an array"},
|
||||
{"arg":"expression","description":"an expression to evaluate on each item. The variable `@element` will be replaced by the current value."}
|
||||
],
|
||||
"examples": [
|
||||
{ "expression": "array_foreach(array('a','b','c'),upper(@element))", "returns":"array: 'A', 'B', 'C'"},
|
||||
{ "expression": "array_foreach(array(1,2,3),@element + 10)", "returns":"array: 11, 12, 13"}
|
||||
]
|
||||
}
|
@ -4729,6 +4729,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "raster_value" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "band" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point" ) ), fcnRasterValue, QStringLiteral( "Rasters" ) )
|
||||
|
||||
// functions for arrays
|
||||
<< new QgsArrayForeachExpressionFunction()
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "array" ), -1, fcnArray, QStringLiteral( "Arrays" ), QString(), false, QSet<QString>(), false, QStringList(), true )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "array_length" ), 1, fcnArrayLength, QStringLiteral( "Arrays" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "array_contains" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "array" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), fcnArrayContains, QStringLiteral( "Arrays" ) )
|
||||
@ -4774,6 +4775,93 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
return sFunctions;
|
||||
}
|
||||
|
||||
QgsArrayForeachExpressionFunction::QgsArrayForeachExpressionFunction()
|
||||
: QgsExpressionFunction( QStringLiteral( "array_foreach" ), 2, QCoreApplication::tr( "Arrays" ) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool QgsArrayForeachExpressionFunction::isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const
|
||||
{
|
||||
bool isStatic = false;
|
||||
|
||||
QgsExpressionNode::NodeList *args = node->args();
|
||||
|
||||
if ( args->count() < 2 )
|
||||
return false;
|
||||
|
||||
if ( args->at( 0 )->isStatic( parent, context ) && args->at( 1 )->isStatic( parent, context ) )
|
||||
{
|
||||
isStatic = true;
|
||||
}
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
QVariant QgsArrayForeachExpressionFunction::run( QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node )
|
||||
{
|
||||
Q_UNUSED( node )
|
||||
QVariantList result;
|
||||
|
||||
if ( args->count() < 2 )
|
||||
// error
|
||||
return result;
|
||||
|
||||
QVariantList array = args->at( 0 )->eval( parent, context ).toList();
|
||||
|
||||
QgsExpressionContext *subContext = const_cast<QgsExpressionContext *>( context );
|
||||
if ( !context )
|
||||
subContext = new QgsExpressionContext();
|
||||
|
||||
QgsExpressionContextScope *subScope = new QgsExpressionContextScope();
|
||||
subContext->appendScope( subScope );
|
||||
|
||||
for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
|
||||
{
|
||||
subScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "element" ), *it, true ) );
|
||||
result << args->at( 1 )->eval( parent, subContext );
|
||||
}
|
||||
|
||||
if ( !context )
|
||||
delete subContext;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant QgsArrayForeachExpressionFunction::func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node )
|
||||
{
|
||||
// This is a dummy function, all the real handling is in run
|
||||
Q_UNUSED( values )
|
||||
Q_UNUSED( context )
|
||||
Q_UNUSED( parent )
|
||||
Q_UNUSED( node )
|
||||
|
||||
Q_ASSERT( false );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool QgsArrayForeachExpressionFunction::prepare( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const
|
||||
{
|
||||
QgsExpressionNode::NodeList *args = node->args();
|
||||
|
||||
if ( args->count() < 2 )
|
||||
// error
|
||||
return false;
|
||||
|
||||
args->at( 0 )->prepare( parent, context );
|
||||
|
||||
QgsExpressionContext subContext;
|
||||
if ( context )
|
||||
subContext = *context;
|
||||
|
||||
QgsExpressionContextScope *subScope = new QgsExpressionContextScope();
|
||||
subScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "element" ), QVariant(), true ) );
|
||||
subContext.appendScope( subScope );
|
||||
|
||||
args->at( 1 )->prepare( parent, &subContext );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsWithVariableExpressionFunction::QgsWithVariableExpressionFunction()
|
||||
: QgsExpressionFunction( QStringLiteral( "with_variable" ), 3, QCoreApplication::tr( "General" ) )
|
||||
{
|
||||
|
@ -498,6 +498,29 @@ class QgsStaticExpressionFunction : public QgsExpressionFunction
|
||||
bool mIsStatic = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the ``array_foreach(array, expression)`` expression function.
|
||||
* It temporarily appends a new scope to the expression context.
|
||||
*
|
||||
* \ingroup core
|
||||
* \note Not available in Python bindings
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
class QgsArrayForeachExpressionFunction : public QgsExpressionFunction
|
||||
{
|
||||
public:
|
||||
QgsArrayForeachExpressionFunction();
|
||||
|
||||
bool isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override;
|
||||
|
||||
QVariant run( QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node ) override;
|
||||
|
||||
QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node ) override;
|
||||
|
||||
bool prepare( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the ``with_variable(name, value, node)`` expression function.
|
||||
* It temporarily appends a new scope to the expression context for all nested
|
||||
|
@ -2687,6 +2687,10 @@ class TestQgsExpression: public QObject
|
||||
concatExpected << QStringLiteral( "a" ) << QStringLiteral( "b" ) << QStringLiteral( "c" );
|
||||
QCOMPARE( QgsExpression( "array_cat(\"strings\", array('a', 'b'), array('c'))" ).evaluate( &context ), QVariant( concatExpected ) );
|
||||
|
||||
QVariantList foreachExpected;
|
||||
foreachExpected << QStringLiteral( "ABC" ) << QStringLiteral( "HELLO" );
|
||||
QCOMPARE( QgsExpression( "array_foreach(array('abc', 'hello'), upper(@element))" ).evaluate( &context ), QVariant( foreachExpected ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_intersect(array('1', '2', '3', '4'), array('4', '0', '2', '5'))" ).evaluate( &context ), QVariant( true ) );
|
||||
QCOMPARE( QgsExpression( "array_intersect(array('1', '2', '3', '4'), array('0', '5'))" ).evaluate( &context ), QVariant( false ) );
|
||||
|
||||
@ -2766,6 +2770,10 @@ class TestQgsExpression: public QObject
|
||||
QCOMPARE( QgsExpression( "array_slice(array(1,2,3,4,5),-2,-1) = array(4,5)" ).evaluate( &context ), QVariant( true ) );
|
||||
QCOMPARE( QgsExpression( "array_slice(array(1,2,3,4,5),-1,-1) = array(5)" ).evaluate( &context ), QVariant( true ) );
|
||||
|
||||
QVariantList foreachExpected;
|
||||
foreachExpected << 10 << 20 << 40;
|
||||
QCOMPARE( QgsExpression( "array_foreach(array(1, 2, 4), @element * 10)" ).evaluate( &context ), QVariant( foreachExpected ) );
|
||||
|
||||
QgsExpression badArray( QStringLiteral( "array_get('not an array', 0)" ) );
|
||||
QCOMPARE( badArray.evaluate( &context ), QVariant() );
|
||||
QVERIFY( badArray.hasEvalError() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user