简体   繁体   中英

Turning a string into a formatted paragraph in JavaScript

Edit: Since people seem a little confused, I will try to clarify.

Essentially, the string you take is a variable character length and can be any number of lines.

The hitch is the string has to not cutoff a word. So, as another example, the string:

'The jumping fox' is divided into 2 separate lines. The middle character is 'u', so the two lines would be: Line 1: 'The jumping' Line 2: 'Fox' to prevent the word being cutoff. So that is the two restrictions.

So, I got this question:

Given a single-line text String and a maximum line value, write the function that formats the input text , ie: Divide the text evenly based on character, and return a new line for each section of the string. But do not cut off a line -- ie, if you have 1000 character, and 2 lines, you can increase the size of the first line to capture the end of the last word in the middle of the 500th character.

I am bashing my head trying to solve it in JavaScript. Any tips? It's easy enough to just return the lines without this whitespace formatting, but I am totally lost.

function formatString(string, numlines) {
  var length = string.length;
  console.log(length);
  var words = string.split(' ');
  var paraLength = parseInt(string.length/numlines);
  console.log(paraLength)

  var paragraph = [];  
  for(var i=0; i<length;) {
    // console.log('i is: ', i);
    console.log('start of string is: ', string.charAt(i));
    console.log('end of string is: ', string.charAt(i+paraLength+1));
    console.log('if true? ', string.indexOf(i) )
    if (string.charAt(i+paraLength) == ' ') {
      var thing = string.substr(i,i+paraLength);
      console.log('if thing is: ', thing);
      i+=paraLength;
      console.log('if i is: ', i);
      paragraph.push(thing);
    } else {
      var thing = string.substr(i,i+paraLength);
      console.log('else thing is: ', thing);
      console.log('blah is: ',i+paraLength+1 >= length);
      while (string.charAt(i+paraLength) != ' ' && i+paraLength < length) {
        thing.concat(string.charAt(i+paraLength+1));
        thing.concat('hi')
        console.log('else thing is: ', thing);
        i+=1;
        console.log('i is: ', i);
      }
      paragraph.push(thing);
      i+= paraLength;
    }
  }

  return paragraph.map(function(d) {
    console.log('d is: ', d);
    return d;
  }).join('')

}
console.log(formatString('hello world blah blah blah', 2));

If I'm understanding you're question, this might help:

function formatString(string, numlines) {
    var length = string.length;
    var paraLength = Math.round((string.length)/numlines);
    var paragraphs = [];
    for (var i=0; i<numlines; i++) {
        var marker = paraLength;
        //if the marker is right after a space, move marker back one character
        if (string.charAt(marker-1) == " ") {
            marker--; 
        }
        //move marker to end of a word if it's in the middle
        while(string.charAt(marker) != " " && string.charAt(marker) != "") {
            marker++;
        }
        var nextPara = string.substring(0, marker)
        paragraphs.push(nextPara)
        string = string.substring((nextPara.length+1),string.length)
    }
    return paragraphs
}

This returns an array that contains the individual paragraphs.

formatString("The jumping fox", 2) // => ["The jumping", "fox"]

The proposed algorithm "you can increase the size of the first line to capture the end of the last word in the middle of the 500th character" has a fatal flaw: if your last word is longer than length(sentence)/num_lines and so you skip to 'the next word', you print out too many words in that line and end up with too little words – probably none at all – in the last line.

This can be solved by not considering a string as a sequence of characters (where you need to inspect each character to see if it is a space) but rather as a sequence of words . Then, the algorithm is that on each line num_words/num_lines must appear. Use Math.ceil to round up, so you are sure that on every line at least one word appears.

With that, you can create a basic test case to split up a list of words exactly in 2. The splitting itself could be done using the split function, but I prefer a regex match , so all spaces are preserved. match returns an array of matches, each of which are a single word plus its following whitespace. Since it's an array, you can divide its length by the number of lines, round up if it's a fraction ( Math.ceil ), then print out those words.

Next? Well, after that step you end up with a not-yet processed remainder of your original string and with a number of lines remaining. So you can call this same function again with the truncated string and one less number of lines. You are done when the number of lines is 1 (then the entire remaining string can be printed) and/or the number of spaces is 0 (not tested for here; I suppose you could first see if you have at least as many spaces-minus-1 as you have lines, and if not, issue an error).

console.log(formatString('hello world blah blah blah', 2));

function formatString (string, numLines)
{
    var wordlist, trim_at, result;
    if (numLines < 2)
        return string;

    wordlist = string.match(/\S+\s*/g);
    trim_at = Math.ceil(wordlist.length/numLines);

    result = '';
    while (trim_at--)
        result += wordlist.shift();
    result += '\n';
    result += formatString (wordlist.join(''), numLines-1);
    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM