Split a string by a delimiter

Problem

You want to split a string on a specified delimiter and return an array of results.

Solution

You can use the Map, FindStrRegex, and Concat functions to achieve the desired result. The following example creates a user-defined function which splits an input string on a specified delimiter and returns the results as elements of an array.

client.query(
  q.CreateFunction({
    name: 'SplitString',
    body: q.Query(
      q.Lambda(
        ['string', 'delimiter'],
        q.If(
          q.Not(q.IsString(q.Var('string'))),
          q.Abort('SplitString only accepts strings'),
          q.Map(
            q.FindStrRegex(
              q.Var('string'),
              q.Concat(['[^\\', q.Var('delimiter'), ']+'])
            ),
            q.Lambda('res', q.Select(['data'], q.Var('res')))
          )
        )
      )
    ),
  })
)
.then((ret) => console.log(ret))
.catch((err) => console.error(
  'Error: [%s] %s: %s',
  err.name,
  err.message,
  err.errors()[0].description,
))
{
  ref: Function("SplitString"),
  ts: 1653676301750000,
  name: 'SplitString',
  body: Query(Lambda(["string", "delimiter"], If(Not(IsString(Var("string"))), Abort("SplitString only accepts strings"), Map(FindStrRegex(Var("string"), Concat(["[^\\", Var("delimiter"), "]+"])), Lambda("res", Select(["data"], Var("res")))))))
}
result = client.query(
  q.create_function({
    "name": "SplitString",
    "body": q.query(
      q.lambda_(
        ["string", "delimiter"],
        q.if_(
          q.not_(q.is_string(q.var("string"))),
          q.abort("SplitString only accepts strings"),
          q.map_(
            q.lambda_("res", q.select(["data"], q.var("res"))),
            q.find_str_regex(
              q.var("string"),
              q.concat(["[^\\", "|", "]+"])
            )
          )
        )
      )
    )
  })
)
print(result)
{'ref': Ref(id=SplitString, collection=Ref(id=functions)), 'ts': 1654031180420000, 'name': 'SplitString', 'body': Query({'api_version': '4', 'lambda': ['string', 'delimiter'], 'expr': {'if': {'not': {'is_string': {'var': 'string'}}}, 'then': {'abort': 'SplitString only accepts strings'}, 'else': {'map': {'lambda': 'res', 'expr': {'select': ['data'], 'from': {'var': 'res'}}}, 'collection': {'findstrregex': {'var': 'string'}, 'pattern': {'concat': ['[^\\', '|', ']+']}}}}})}
res, err := client.Query(
	f.CreateFunction(f.Obj{
		"name": "SplitString",
		"body": f.Query(
			f.Lambda(
				f.Arr{"string", "delimiter"},
				f.If(
					f.Not(f.IsString(f.Var("string"))),
					f.Abort("SplitString only accepts strings"),
					f.Map(
						f.FindStrRegex(
							f.Var("string"),
							f.Concat(
								f.Arr{
									"[^\\",
									f.Var("delimiter"),
									"]+",
								},
							),
						),
						f.Lambda("res", f.Select(f.Arr{"data"}, f.Var("res")))))))}))

if err != nil {
	fmt.Fprintln(os.Stderr, err)
} else {
	fmt.Println(res)
}
map[body:{[123 34 97 112 105 95 118 101 114 115 105 111 110 34 58 34 52 34 44 34 108 97 109 98 100 97 34 58 91 34 115 116 114 105 110 103 34 44 34 100 101 108 105 109 105 116 101 114 34 93 44 34 101 120 112 114 34 58 123 34 105 102 34 58 123 34 110 111 116 34 58 123 34 105 115 95 115 116 114 105 110 103 34 58 123 34 118 97 114 34 58 34 115 116 114 105 110 103 34 125 125 125 44 34 116 104 101 110 34 58 123 34 97 98 111 114 116 34 58 34 83 112 108 105 116 83 116 114 105 110 103 32 111 110 108 121 32 97 99 99 101 112 116 115 32 115 116 114 105 110 103 115 34 125 44 34 101 108 115 101 34 58 123 34 109 97 112 34 58 123 34 108 97 109 98 100 97 34 58 34 114 101 115 34 44 34 101 120 112 114 34 58 123 34 115 101 108 101 99 116 34 58 91 34 100 97 116 97 34 93 44 34 102 114 111 109 34 58 123 34 118 97 114 34 58 34 114 101 115 34 125 125 125 44 34 99 111 108 108 101 99 116 105 111 110 34 58 123 34 102 105 110 100 115 116 114 114 101 103 101 120 34 58 123 34 118 97 114 34 58 34 115 116 114 105 110 103 34 125 44 34 112 97 116 116 101 114 110 34 58 123 34 99 111 110 99 97 116 34 58 91 34 91 94 92 92 34 44 123 34 118 97 114 34 58 34 100 101 108 105 109 105 116 101 114 34 125 44 34 93 43 34 93 125 125 125 125 125]} name:SplitString ref:{SplitString 0xc0000a0240 0xc0000a0240 <nil>} ts:1654048374850000]
try
{
    Value result = await client.Query(
        CreateFunction(Obj(
            "name", "SplitString",
            "body", Query(
                Lambda(
                    Arr("string", "delimiter"),
                    If(
                        Not(IsString(Var("string"))),
                        Abort("SplitString only accepts strings"),
                        Map(
                            FindStrRegex(
                                Var("string"),
                                Concat(
                                    Arr(
                                        "[^\\",
                                        Var("delimiter"),
                                        "]+"
                                    )
                                )
                            ),
                            Lambda("res", Select(Arr("data"), Var("res")))
                        )
                    )
                )
            )
        ))
    );
    Console.WriteLine(result);
}
catch (Exception e)
{
    Console.WriteLine($"ERROR: {e.Message}");
}
ObjectV(ref: RefV(id = "SplitString", collection = RefV(id = "functions")),ts: LongV(1653676658410000),name: StringV(SplitString),body: QueryV(System.Collections.Generic.Dictionary`2[System.String,FaunaDB.Query.Expr]))
CreateFunction({
  name: 'SplitString',
  body: Query(
    Lambda(
      ['string', 'delimiter'],
      If(
        Not(IsString(Var("string"))),
        Abort("SplitString only accepts strings"),
        Map(
          FindStrRegex(
            Var("string"),
            Concat(["[^\\", Var("delimiter"), "]+"])
          ),
          Lambda("res", Select(["data"], Var("res")))
        )
      )
    )
  )
})
{
  ref: Function("SplitString"),
  ts: 1653676193440000,
  name: 'SplitString',
  body: Query(Lambda(["string", "delimiter"], If(Not(IsString(Var("string"))), Abort("SplitString only accepts strings"), Map(FindStrRegex(Var("string"), Concat(["[^\\", Var("delimiter"), "]+"])), Lambda("res", Select(["data"], Var("res")))))))
}
Query metrics:
  •    bytesIn:  391

  •   bytesOut:  491

  • computeOps:    1

  •    readOps:    0

  •   writeOps:    1

  •  readBytes:   24

  • writeBytes:  582

  •  queryTime: 29ms

  •    retries:    0

Once your SplitString UDF is created, you can use it to split strings on a specified delimiter.

client.query(
  q.Call('SplitString', 'red|blue|pink', '|')
)
.then((ret) => console.log(ret))
.catch((err) => console.error(
  'Error: [%s] %s: %s',
  err.name,
  err.message,
  err.errors()[0].description,
))
[ 'red', 'blue', 'pink' ]
result = client.query(
  q.call("SplitString", "red|blue|pink", "|")
)
print(result)
["red", "blue", "pink"]
res, err := client.Query(
	f.Call("SplitString", "red|blue|pink", "|"))

if err != nil {
	fmt.Fprintln(os.Stderr, err)
} else {
	fmt.Println(res)
}
[red blue pink]
try
{
    Value result = await client.Query(
        Call("SplitString", "red|blue|pink", "|")
    );
    Console.WriteLine(result);
}
catch (Exception e)
{
    Console.WriteLine($"ERROR: {e.Message}");
}
Arr(StringV(red), StringV(blue), StringV(pink))
Call("SplitString", "red|blue|pink", "|")
[ 'red', 'blue', 'pink' ]
Query metrics:
  •    bytesIn:  56

  •   bytesOut:  34

  • computeOps:   1

  •    readOps:   0

  •   writeOps:   0

  •  readBytes:   0

  • writeBytes:   0

  •  queryTime: 9ms

  •    retries:   0

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!