Skip to content

Commit

Permalink
[FEATURE] array support for the replace() expression function
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Oct 26, 2016
1 parent 8589788 commit 8b74201
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 7 deletions.
10 changes: 6 additions & 4 deletions resources/function_help/json/replace
@@ -1,10 +1,12 @@
{
"name": "replace",
"type": "function",
"description": "Returns a string with the the supplied string replaced.",
"description": "Returns a string with the supplied string or array of strings replaced by a string or an array of strings.",
"arguments": [ {"arg":"string","description":"the input string"},
{"arg":"before","description":"the string to replace"},
{"arg":"after","description":"the string to use as a replacement"}],
"examples": [ { "expression":"replace('QGIS SHOULD ROCK','SHOULD','DOES')", "returns":"'QGIS DOES ROCK'"}
{"arg":"before","description":"the string or array of strings to replace"},
{"arg":"after","description":"the string or array of strings to use as a replacement"}],
"examples": [ { "expression":"replace('QGIS SHOULD ROCK','SHOULD','DOES')", "returns":"'QGIS DOES ROCK'"},
{ "expression":"replace('QGIS ABC',array('A','B','C'),array('X','Y','Z'))", "returns":"'QGIS XYZ'"},
{ "expression":"replace('QGIS',array('Q','S'),'')", "returns":"'GI'"}
]
}
38 changes: 35 additions & 3 deletions src/core/qgsexpression.cpp
Expand Up @@ -1215,9 +1215,41 @@ static QVariant fcnLength( const QVariantList& values, const QgsExpressionContex
static QVariant fcnReplace( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QString str = getStringValue( values.at( 0 ), parent );
QString before = getStringValue( values.at( 1 ), parent );
QString after = getStringValue( values.at( 2 ), parent );
return QVariant( str.replace( before, after ) );
QVariantList before;
QVariantList after;
bool isSingleReplacement = false;

if ( values.at( 1 ).type() != QVariant::List && values.at( 2 ).type() != QVariant::StringList )
{
before = QVariantList() << getStringValue( values.at( 1 ), parent );
}
else
{
before = getListValue( values.at( 1 ), parent );
}

if ( values.at( 2 ).type() != QVariant::List && values.at( 2 ).type() != QVariant::StringList )
{
after = QVariantList() << getStringValue( values.at( 2 ), parent );
isSingleReplacement = true;
}
else
{
after = getListValue( values.at( 2 ), parent );
}

if ( !isSingleReplacement && before.length() != after.length() )
{
parent->setEvalErrorString( QObject::tr( "Invalid pair of array, length not identical" ) );
return QVariant();
}

for ( int i = 0; i < before.length(); i++ )
{
str = str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
}

return QVariant( str );
}
static QVariant fcnRegexpReplace( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
Expand Down
4 changes: 4 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -821,6 +821,10 @@ class TestQgsExpression: public QObject
QTest::newRow( "upper" ) << "upper('HeLLo')" << false << QVariant( "HELLO" );
QTest::newRow( "length" ) << "length('HeLLo')" << false << QVariant( 5 );
QTest::newRow( "replace" ) << "replace('HeLLo', 'LL', 'xx')" << false << QVariant( "Hexxo" );
QTest::newRow( "replace (array replaced by array)" ) << "replace('321', array('1','2','3'), array('7','8','9'))" << false << QVariant( "987" );
QTest::newRow( "replace (array replaced by string)" ) << "replace('12345', array('2','4'), '')" << false << QVariant( "135" );
QTest::newRow( "replace (unbalanced array, before > after)" ) << "replace('12345', array('1','2','3'), array('6','7'))" << true << QVariant();
QTest::newRow( "replace (unbalanced array, before < after)" ) << "replace('12345', array('1','2'), array('6','7','8'))" << true << QVariant();
QTest::newRow( "regexp_replace" ) << "regexp_replace('HeLLo','[eL]+', '-')" << false << QVariant( "H-o" );
QTest::newRow( "regexp_replace greedy" ) << "regexp_replace('HeLLo','(?<=H).*L', '-')" << false << QVariant( "H-o" );
QTest::newRow( "regexp_replace non greedy" ) << "regexp_replace('HeLLo','(?<=H).*?L', '-')" << false << QVariant( "H-Lo" );
Expand Down

0 comments on commit 8b74201

Please sign in to comment.