How to split string by number of characters in Dataweave

Viewed 1740

hi i could not find a function in Dataweave to split a string by a specified length .

The string i need to split is

ThisistheStringineedtoSplit

Expected out put is an array with all the substrings

payload.splitBy(sizeOf(payload)/10)

[ThisistheString,ineedtoSplit]
3 Answers

We can use a recursive function along with the built in functionality around string indexes. With strings, you can select a substring easily like [0 to end]. To then get the rest of the string you can do [end to -1]. Using a negative index translates to an index from the back, so -1 will be the last character. Since this is a zero index, we grab [0 to size - 1] to get the right number of characters, and then just recursively call again on [size to -1].

%dw 2.0
output application/json

fun divideBy(str: String, size: Number): Array<String> =
    if (sizeOf(str) <= size) [str]
    else [str[0 to size - 1]] ++ divideBy(str[size to -1], size)

var message = "ThisistheStringineedtoSplit"

---
message divideBy 10

Output:

[
  "ThisistheS",
  "tringineed",
  "toSplit"
]

In your example output, the substrings are longer than 10 characters. Was that a mistake, or am I misunderstanding what you want?

Edit:

You could also do this with some regex, though I don't think there is any real gain here.. I just happened to have regex on the mind from a conversation yesterday.

%dw 2.0
output application/json

fun divideBy(str: String, size: Number): Array<String> = 
    flatten(str scan ".{1,$(size)}")

var message = "ThisistheStringineedtoSplit"

---
message divideBy 10

Here's another approach

%dw 2.0
import * from dw::core::Arrays
output application/json

var myStringAsArray = "awefawefwaefawefwaefawefwa" splitBy  ""
var denominator = 10

---
 
(myStringAsArray divideBy denominator) map ($ joinBy "")

I believe above answers are not complete.

  1. The selected answer is using a recursive call which means that you are limited to the java stack size in Mule/Dataweave.
  2. The other approach uses splitBy "" which splits by every single character and map to iterate on every single character then joinBy that, again, adds work on every single character. This is ok for a string of 10 characters, anything above that you will face massive performance issues, or even crash of the Mule Runtime.

In order to be good in performance and out of limitation, we need to use tail recursion.

%dw 2.0
output application/json

import first, last from dw::core::Strings

var splitSize = 1000

fun tailRecursiveSplit(str: String, size: Number, arr: Array<String> = []) = 
    if ( sizeOf(str) > size ) tailRecursiveSplit(last(str,sizeOf(str)-size), size, arr + first(str,size)) else (arr + str)
---
tailRecursiveSplit(payload as String, splitSize)

Doc used to create the above code: How to untie multilevel structures with DataWeave recursive calls

Related