Skip to content

Commit

Permalink
Merge pull request #3678 from nirvn/string_to_array_to_string
Browse files Browse the repository at this point in the history
[FEATURE] add string_to_array() and array_to_string() functions
  • Loading branch information
nyalldawson authored Oct 27, 2016
2 parents 0f7babb + 7373036 commit fb45781
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
12 changes: 12 additions & 0 deletions resources/function_help/json/array_to_string
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "array_to_string",
"type": "function",
"description": "Concatenates array elements into a string separated by a delimiter using and optional string for empty values.",
"arguments": [
{"arg":"array", "description":"the input array"},
{"arg":"delimiter","optional":true,"default":"','","description":"the string delimiter used to separate concatenated array elements"},
{"arg":"emptyvalue","optional":true,"default":"''","description":"the optional string to use as replacement to empty values"}],
"examples": [ { "expression":"array_to_string(array('1','2','3'),',')", "returns":"'1,2,3'"},
{ "expression":"array_to_string(array('1','','3'),',','0')", "returns":"'1,0,3'"}
]
}
12 changes: 12 additions & 0 deletions resources/function_help/json/string_to_array
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "string_to_array",
"type": "function",
"description": "Splits string into an array using supplied delimiter and optional string for empty values.",
"arguments": [
{"arg":"string", "description":"the input string"},
{"arg":"delimiter","optional":true,"default":"','","description":"the string delimiter used to split the input string"},
{"arg":"emptyvalue","optional":true,"default":"''","description":"the optional string to use as replacement to empty values"}],
"examples": [ { "expression":"string_to_array('1,2,3',',')", "returns":"array: '1', '2', '3'"},
{ "expression":"string_to_array('1,,3',',','0')", "returns":"array: '1', '0', '3'"}
]
}
39 changes: 39 additions & 0 deletions src/core/qgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3395,6 +3395,43 @@ static QVariant fcnArrayIntersect( const QVariantList& values, const QgsExpressi
return QVariant( false );
}

static QVariant fcnArrayToString( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QVariantList array = getListValue( values.at( 0 ), parent );
QString delimiter = getStringValue( values.at( 1 ), parent );
QString empty = getStringValue( values.at( 2 ), parent );

QString str;

for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
{
str += ( *it ).toString().isEmpty() == false ? ( *it ).toString() : empty;
if ( it != ( array.constEnd() - 1 ) )
{
str += delimiter;
}
}

return QVariant( str );
}

static QVariant fcnStringToArray( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QString str = getStringValue( values.at( 0 ), parent );
QString delimiter = getStringValue( values.at( 1 ), parent );
QString empty = getStringValue( values.at( 2 ), parent );

QStringList list = str.split( delimiter );
QVariantList array;

for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
{
array += ( *it ).isEmpty() == false ? *it : empty;
}

return array;
}

static QVariant fcnMap( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QVariantMap result;
Expand Down Expand Up @@ -3778,6 +3815,8 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( QStringLiteral( "array_remove_all" ), ParameterList() << Parameter( QStringLiteral( "array" ) ) << Parameter( QStringLiteral( "value" ) ), fcnArrayRemoveAll, QStringLiteral( "Arrays" ) )
<< new StaticFunction( QStringLiteral( "array_cat" ), -1, fcnArrayCat, QStringLiteral( "Arrays" ) )
<< new StaticFunction( QStringLiteral( "array_intersect" ), ParameterList() << Parameter( QStringLiteral( "array1" ) ) << Parameter( QStringLiteral( "array2" ) ), fcnArrayIntersect, QStringLiteral( "Arrays" ) )
<< new StaticFunction( QStringLiteral( "array_to_string" ), ParameterList() << Parameter( QStringLiteral( "array" ) ) << Parameter( QStringLiteral( "delimiter" ), true, "," ) << Parameter( QStringLiteral( "emptyvalue" ), true, "" ), fcnArrayToString, QStringLiteral( "Arrays" ) )
<< new StaticFunction( QStringLiteral( "string_to_array" ), ParameterList() << Parameter( QStringLiteral( "string" ) ) << Parameter( QStringLiteral( "delimiter" ), true, "," ) << Parameter( QStringLiteral( "emptyvalue" ), true, "" ), fcnStringToArray, QStringLiteral( "Arrays" ) )

//functions for maps
<< new StaticFunction( QStringLiteral( "map" ), -1, fcnMap, QStringLiteral( "Maps" ) )
Expand Down
5 changes: 5 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,9 @@ class TestQgsExpression: public QObject
QTest::newRow( "concat" ) << "concat('a', 'b', 'c', 'd')" << false << QVariant( "abcd" );
QTest::newRow( "concat function single" ) << "concat('a')" << false << QVariant( "a" );
QTest::newRow( "concat function with NULL" ) << "concat(NULL,'a','b')" << false << QVariant( "ab" );
QTest::newRow( "array_to_string" ) << "array_to_string(array(1,2,3),',')" << false << QVariant( "1,2,3" );
QTest::newRow( "array_to_string with custom empty value" ) << "array_to_string(array(1,'',3),',','*')" << false << QVariant( "1,*,3" );
QTest::newRow( "array_to_string fail passing non-array" ) << "array_to_string('non-array',',')" << true << QVariant();

//fuzzy matching
QTest::newRow( "levenshtein" ) << "levenshtein('kitten','sitting')" << false << QVariant( 3 );
Expand Down Expand Up @@ -2229,8 +2232,10 @@ class TestQgsExpression: public QObject
QCOMPARE( QgsExpression( "array()" ).evaluate( &context ), QVariant( builderExpected ) );
builderExpected << "hello";
QCOMPARE( QgsExpression( "array('hello')" ).evaluate( &context ), QVariant( builderExpected ) );
QCOMPARE( QgsExpression( "string_to_array('hello',',')" ).evaluate( &context ), QVariant( builderExpected ) );
builderExpected << "world";
QCOMPARE( QgsExpression( "array('hello', 'world')" ).evaluate( &context ), QVariant( builderExpected ) );
QCOMPARE( QgsExpression( "string_to_array('hello,world',',')" ).evaluate( &context ), QVariant( builderExpected ) );

QCOMPARE( QgsExpression( "array_length(\"strings\")" ).evaluate( &context ), QVariant( 2 ) );

Expand Down

0 comments on commit fb45781

Please sign in to comment.