Platiplus
Platiplus

Reputation: 107

Reshape String, inserting "\n" at every N characters

Using JavaScript functions, I was trying to insert a breakline on a string at every N characters provided by the user.

Just like this: function("blabla", 3) would output "bla\nbla\n".

I searched a lot of answers and ended up with a regex to do that, the only problem is, I need the user's input on the matter, so I need to stuck a variable on this regex.

Here's the code:

function reshapeString(string, num) {
    var regex = new RegExp("/(.{" + num + "})/g");
    return string.replace(regex,"$1\n");
}

reshapeString("blablabla", 3);

This is currently not working. I tried to escape the '/' characters, but I'm screwing up at some point and I don't know where.

What am I missing? Is there any other way to solve the problem of reshaping this string?

Upvotes: 5

Views: 9332

Answers (4)

Atif Mehar
Atif Mehar

Reputation: 11

public static String reshape(int n, String str){

    StringBuilder sb = new StringBuilder();

    char[] c = str.replaceAll(" " , "").toCharArray();
        int count =0;
        for (int i = 0; i < c.length; i++) {
            if(count != n){
                sb.append(c[i]);
                count++;
             }else {
                count = 1;
                sb.append("\n").append(c[i]);
            }
        }

    return sb.toString();
}

Upvotes: 1

Redu
Redu

Reputation: 26191

Strings are immutable so whatever you do you have to create a new string. It's best to start creating it in the first place.

var newLineForEach = (n,s) => s && `${s.slice(0,n)}\n${newLineForEach(n,s.slice(n))}`,
    result = newLineForEach(3,"blablabla");
console.log(result);

So my tests show that this is by far the fastest. 100K iterations resulted Nina's 1260msec, AP's 103msec and Redu's 33msec. The accepted answer is very inefficient.

Upvotes: 0

AP.
AP.

Reputation: 8931

How about a one-liner?

const reshapeString = (str,N) => str.split('').reduce((o,c,i) => o+(!i || i%N?'':'\n')+c, '')

Explanation:

  • So first thing we do is split the string into a character array
  • Now we use a reduce() statement to go through each element and reduce to a single value (ie. the final string you're looking for!)
  • Now i%N should give a non-zero (ie. a truthy value) when the index is not a multiple of N, so we just add the current character to out accumulator variable o.
  • If i%N is in fact 0 (then it's falsey in value), and we append:
    • o (the string so far) +
    • \n (the appended character at the N'th interval)
    • c (the current character)
  • Note: We also have a !i check, that's for ignoring the first char since, that may be considered un-intended behavior

Benchmarking

Regex construction and replace also requires string re-construction and creating an FSA to follow. Which for strings smaller than 1000 should be slower

Test:

(_ => {
    const reshapeString_AP = (str,N) => str.split('').reduce((o,c,i) => o+(!i || i%N?'':'\n')+c, '')
    function reshapeString_Nina(string, num) {
        var regex = new RegExp(".{" + num + "}", "g");
        return string.replace(regex,"$&\n");
    }

    const payload = 'a'.repeat(100)
    console.time('AP');
    reshapeString_AP(payload, 4)
    console.timeEnd('AP');
    console.time('Nina');
    reshapeString_Nina(payload, 4)
    console.timeEnd('Nina');
})()

Results (3 runs):

AP: 0.080078125ms
Nina: 0.13916015625ms
---
AP: 0.057861328125ms
Nina: 0.119140625ms
---
AP: 0.070068359375ms
Nina: 0.116943359375ms

Upvotes: 3

Nina Scholz
Nina Scholz

Reputation: 386730

You need a string for the regexp constructor, without /, and you can omit the group by using $& for the found string.

function reshapeString(string, num) {
    var regex = new RegExp(".{" + num + "}", "g");
    return string.replace(regex,"$&\n");
}

console.log(reshapeString("blablabla", 3));

Upvotes: 4

Related Questions