Khant
Khant

Reputation: 1122

How to find in string in the syntax and split them into an array regardless of order?

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?

Upvotes: 0

Views: 54

Answers (2)

jabaa
jabaa

Reputation: 6745

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);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386540

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);

Upvotes: 0

Related Questions