Skip to content

Commit 8b74201

Browse files
committed
[FEATURE] array support for the replace() expression function
1 parent 8589788 commit 8b74201

File tree

3 files changed

+45
-7
lines changed

3 files changed

+45
-7
lines changed

resources/function_help/json/replace

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
{
22
"name": "replace",
33
"type": "function",
4-
"description": "Returns a string with the the supplied string replaced.",
4+
"description": "Returns a string with the supplied string or array of strings replaced by a string or an array of strings.",
55
"arguments": [ {"arg":"string","description":"the input string"},
6-
{"arg":"before","description":"the string to replace"},
7-
{"arg":"after","description":"the string to use as a replacement"}],
8-
"examples": [ { "expression":"replace('QGIS SHOULD ROCK','SHOULD','DOES')", "returns":"'QGIS DOES ROCK'"}
6+
{"arg":"before","description":"the string or array of strings to replace"},
7+
{"arg":"after","description":"the string or array of strings to use as a replacement"}],
8+
"examples": [ { "expression":"replace('QGIS SHOULD ROCK','SHOULD','DOES')", "returns":"'QGIS DOES ROCK'"},
9+
{ "expression":"replace('QGIS ABC',array('A','B','C'),array('X','Y','Z'))", "returns":"'QGIS XYZ'"},
10+
{ "expression":"replace('QGIS',array('Q','S'),'')", "returns":"'GI'"}
911
]
1012
}

src/core/qgsexpression.cpp

+35-3
Original file line numberDiff line numberDiff line change
@@ -1215,9 +1215,41 @@ static QVariant fcnLength( const QVariantList& values, const QgsExpressionContex
12151215
static QVariant fcnReplace( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
12161216
{
12171217
QString str = getStringValue( values.at( 0 ), parent );
1218-
QString before = getStringValue( values.at( 1 ), parent );
1219-
QString after = getStringValue( values.at( 2 ), parent );
1220-
return QVariant( str.replace( before, after ) );
1218+
QVariantList before;
1219+
QVariantList after;
1220+
bool isSingleReplacement = false;
1221+
1222+
if ( values.at( 1 ).type() != QVariant::List && values.at( 2 ).type() != QVariant::StringList )
1223+
{
1224+
before = QVariantList() << getStringValue( values.at( 1 ), parent );
1225+
}
1226+
else
1227+
{
1228+
before = getListValue( values.at( 1 ), parent );
1229+
}
1230+
1231+
if ( values.at( 2 ).type() != QVariant::List && values.at( 2 ).type() != QVariant::StringList )
1232+
{
1233+
after = QVariantList() << getStringValue( values.at( 2 ), parent );
1234+
isSingleReplacement = true;
1235+
}
1236+
else
1237+
{
1238+
after = getListValue( values.at( 2 ), parent );
1239+
}
1240+
1241+
if ( !isSingleReplacement && before.length() != after.length() )
1242+
{
1243+
parent->setEvalErrorString( QObject::tr( "Invalid pair of array, length not identical" ) );
1244+
return QVariant();
1245+
}
1246+
1247+
for ( int i = 0; i < before.length(); i++ )
1248+
{
1249+
str = str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1250+
}
1251+
1252+
return QVariant( str );
12211253
}
12221254
static QVariant fcnRegexpReplace( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
12231255
{

tests/src/core/testqgsexpression.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,10 @@ class TestQgsExpression: public QObject
821821
QTest::newRow( "upper" ) << "upper('HeLLo')" << false << QVariant( "HELLO" );
822822
QTest::newRow( "length" ) << "length('HeLLo')" << false << QVariant( 5 );
823823
QTest::newRow( "replace" ) << "replace('HeLLo', 'LL', 'xx')" << false << QVariant( "Hexxo" );
824+
QTest::newRow( "replace (array replaced by array)" ) << "replace('321', array('1','2','3'), array('7','8','9'))" << false << QVariant( "987" );
825+
QTest::newRow( "replace (array replaced by string)" ) << "replace('12345', array('2','4'), '')" << false << QVariant( "135" );
826+
QTest::newRow( "replace (unbalanced array, before > after)" ) << "replace('12345', array('1','2','3'), array('6','7'))" << true << QVariant();
827+
QTest::newRow( "replace (unbalanced array, before < after)" ) << "replace('12345', array('1','2'), array('6','7','8'))" << true << QVariant();
824828
QTest::newRow( "regexp_replace" ) << "regexp_replace('HeLLo','[eL]+', '-')" << false << QVariant( "H-o" );
825829
QTest::newRow( "regexp_replace greedy" ) << "regexp_replace('HeLLo','(?<=H).*L', '-')" << false << QVariant( "H-o" );
826830
QTest::newRow( "regexp_replace non greedy" ) << "regexp_replace('HeLLo','(?<=H).*?L', '-')" << false << QVariant( "H-Lo" );

0 commit comments

Comments
 (0)