I need to split an array based on a dynamic separator that will change, and keep the separator in the resulting array.
Consider the following example where I need to:
-
Split
const match = 'somethingcatsomethingcatsomethingcat'
-
using the separator
const separator = 'cat'
-
and get the following array as a result:
["something", "cat", "something", "cat", "something", "cat"]
.
Here’s what I’ve tried:
const separator = 'cat'
const match = 'somethingcatsomethingcatsomethingcat'
const standardSplit = match.split(separator)
console.log(standardSplit)
// >> Array ["something", "something", "something", ""]
const withPureRegex = match.split(/(cat)/)
console.log(withPureRegex)
// >> Array ["something", "cat", "something", "cat", "something", "cat", ""]
// This is what I need, without the last element of an empty string.
// But I need to pass in the separator dynamically.
const regex = new RegExp(`/(${separator})/`, 'gi')
const withStringLiteral = match.split(regex)
console.log(withStringLiteral)
// >> Array ["somethingcatsomethingcatsomethingcat"]
I’m no good with regex. I’ve read some articles about escaping in regex, but it seems it’s not necessary within RegExp
? I tried many variations of the RegExp
with no luck.
There are a good number of questions regarding this, but only few I’ve found that attempt to do it with a dynamic separator. The few questions I found had answers using string literals and RegExp
like I have above.
If I needed to do this only once, I would use a non-regex approach, like using the first split
method above and then manually looping through to insert the separator as needed. But in this case I’m running this match/replace many times and can’t add more overhead if it could be avoided.
3
Answers
You can remove the last empty item using
.filter(Boolean)
.Demo:
You can split on matches of the regular expression
The expression reads, "match zero or more spaces provided they are not proceeded by a space or at the beginning of the string, and are followed by
"cat"
or (|
) match zero or more spaces provided they are preceded by"cat"
and are not followed by a space or at the end of the string.(?=cat)
is a positive lookahead;(?<=cat)
is a positive lookbehind.(?<!^| )
is a negative lookbehind;(?! |$)
is a negative lookahead.Demo
The link demonstrates that the two strings
are both split into the array
Note that some of matches on which the string is split may be zero-width, such as when splitting the string
"catsomething"
into"cat"
and"something"
.The goofy
(?<! |^)
is to split, for example," catsomething"
into" cat"
and"something"
. Had I used(?<!^)
that string would have been split into" "
,"cat"
and"something"
. Similar for(?! |$)
instead of(?!$)
.Here’s a non-regex way of doing this:
`,${separator},`
,
Note I’ve used
,
as a new separator; you can use any character that doesn’t occur in the original string.