0

I am trying to split an string into separate parts. Here how I want

I got an original string

let allString =  'This is the test to replace the string';

I will make the original string into array according to an array.

let toReplace = [
    {
        string: 'the test'
    },
    {
        string: 'replace'
    },
]

The result I want [ 'This is ', 'the test', ' to ', 'replace', ' the string' ].

I got the answer for this already

const processedText = toReplace
    .reduce(
      (result, { string }, index) => {
        const parts = result[result.length - 1].split(string);
        const [before, after] = parts;

        const newResult = result.slice();
        const firstPass = index === 0;
        if (firstPass) {
          newResult.shift();
        } else {
          newResult.pop();
        }

        if (before) {
          newResult.push(before);
        }
        if (string) {
          newResult.push(string);
        }
        if (after) {
          newResult.push(after);
        }

        return newResult;
      },
      [allString]
   )

The thing is if I change the order of the toReplace array, It won't work anymore

let toReplace = [
        {
            string: 'replace'
        },
        {
            string: 'the test'
        },
    ]

It will skip the 2nd one. Result [ 'This is the test to ', 'replace', ' the string', 'the test' ]

How can I fix this behavior?

0

2 Answers 2

1

You can pass a regular expression to split. Using capturing groups will keep the separator in the array:

let allString = 'This is the test to replace the string';

const processedText = allString.split(/(the test|replace)/);
console.log(processedText);

The order isn't important for this:

let allString = 'This is the test to replace the string';

const processedText = allString.split(/(replace|the test)/);
console.log(processedText);

You can dynamically build the regular expression:

let toReplace = [{ string: 'the test' }, { string: 'replace' }];

const re = new RegExp(`(${toReplace.map(el => el.string).join('|')})`);

let allString = 'This is the test to replace the string';

const processedText = allString.split(re);
console.log(processedText);

Sign up to request clarification or add additional context in comments.

3 Comments

How about this case let toReplace = [{ string: '*' }, { string: 'replace' }]; I am getting the error of Nothing to repeat when allString = 'This is * the test to replace the string'
@Khant You could use \* instead of *. This is because * has a special meaning in a regular expression.
@Khant Or replace el.string with el.string.replace('*', '\*').
0

You could collect the indices of the wanted prases and sort the array by index and get the sliced array with it.

const
    text =  'This is the test to replace the string',
    toReplace = [{ string: 'replace' }, { string: 'the test' }],
    indices = [],
    result = [];

for (const { string } of toReplace) {
    let i = text.indexOf(string);
    while (i !== -1) {
        indices.push([i, string]);
        i = text.indexOf(string, i + string.length);
    }
}

indices.sort(([a], [b]) => a - b);

let i = 0, j = 0;

if (indices[j]?.[0] === 0) {
    result.push(indices[j][1]);
    i += indices[j][1].length;
    j++;
}

while (i < text.length && j < indices.length) {
    result.push(text.slice(i, indices[j][0]), indices[j][1]);
    i = indices[j][0] + indices[j][1].length;
    j++;
}

if (text.slice(i)) result.push(text.slice(i));

console.log(result);
console.log(indices);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.