skip to Main Content

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


  1. You can remove the last empty item using .filter(Boolean).

    Demo:

    const match = 'somethingcatsomethingcatsomethingcat';
    const separator = 'cat';
    
    const reg = new RegExp(`(${separator})`, 'g');
    const resArr = match.split(reg).filter(Boolean);
    
    console.log(resArr);
    Login or Signup to reply.
  2. You can split on matches of the regular expression

    (?<!^| ) *(?=cat)|(?<=cat) *(?! |$)
    

    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

    "catsomethingcatsomethingcat"
    "cat somethingcatsomething cat"
    

    are both split into the array

    ["cat", "something", "cat", "something", "cat"]
    

    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 (?!$).

    Login or Signup to reply.
  3. Here’s a non-regex way of doing this:

    • split on the separator
    • re-join the array using `,${separator},`
    • split the new string on ,
    • filter out any empty values

    Note I’ve used , as a new separator; you can use any character that doesn’t occur in the original string.

    const separator = 'cat'
    const match = 'somethingcatsomethingcatsomethingcat'
    
    const result = match.split(separator)
      .join(`,${separator},`)
      .split(',')
      .filter(Boolean)
    
    console.log(result)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search