dpg5000
dpg5000

Reputation: 363

adding a space to every space in a string, then cycling back around until length is met

I have the following while loop as part of my text justify function. The idea is that I have text strings (str) that need to be justified (spaces added to existing spaces in between words) to equal to a given length (len)

The catch is I can only add one space to an existing space at a time before I iterate over to the next space in the string and add another space there. If that's it for all spaces in the string and it's still not at the required length, I cycle back over to the original space (now two spaces) and add another. Then it goes to the next space between words and so on and so on. The idea is that any spaces between words in the string should not have a differential of more than one space (i.e. Lorem---ipsum--dolor--sit, not Lorem----ipsum--dolor-sit)

From my research, I decided that using a substring method off the original string to add that first extra space, then I will increment the index and move to the next space in the string and repeat the add. Here's my code:

var indexOf = str.indexOf(" ", 0);

if ( indexOf > -1 ) {
    while ( indexOf > -1 && str.length < len ) {
        //using a regexp to find a space before a character
        var space  = /\s(?=\b)/.exec(str);
        str = str.substring(0, indexOf + 1) + " " + str.substring(indexOf + 1);
        //go to next space in string
        indexOf = str.indexOf(space, indexOf + 2);

        if ( indexOf === -1 ) {
            //loops back to beginning of string
            indexOf = str.indexOf(space, 0);
        }

    }
}
finalResults.push(str);                           

This code works most of the time, but I noticed that there are instances where the cycle of spacing is not correct. For example, it generates the following string: sit----amet,--blandit when the correct iteration would be sit---amet,---blandit

Any assistance in making this code properly iterate over every space (to add one space) in the string once, then cycling back around to the beginning of the string to start over until the desired length is achieved would be most appreciated.

Upvotes: 0

Views: 287

Answers (3)

HBP
HBP

Reputation: 16033

This function adds the spaces using a global replace, carefully limiting the text size.

 function expand (txt, colwidth) {
   txt = txt.replace (/\s\s+/, ' ');        // Ensure no multiple spaces in txt

   for (var spaces = ' ',                   // Spaces to check for
            limit = colwidth - txt.length;  // number of additional spaces required
        limit > 0;                          // do while limit is positive
        spaces += ' ')                      // add 1 to spaces to search for
    txt = txt.replace (RegExp (spaces, 'g'), 
              function (r) { 
                // If limit > 0  then add a space else do not.
                return limit > 0 && --limit ? r + ' ' : r 
              });
    return txt;
 }

 for (var w = 21; w--;) console.log (expand ('this is a test.', w)); 

Shows this on console:

    this   is  a  test.
    this  is  a  test.
    this  is  a test.
    this  is a test.
 14 this is a test.

Upvotes: 1

D&#233;j&#224; vu
D&#233;j&#224; vu

Reputation: 28840

This solution

  • splits the string (s) into words in an array (a)
  • finds the number of spaces to be added between all words (add)
  • finds the remainder of spaces to be added between first words (rem)
  • then sticks the words with add spaces + one if rem is not exhausted

Code

var  s = "Caballo sin Nombre"; // assume one space between words
var len = 21; // desired length

var need = len - s.length;
var a = s.split(/ /); // split s

// need>0 and at least two words
if (need > 0 && a.length>1) {
     var add = Math.floor(need / (a.length-1)) + 1; // all spaces need that (+existing)
     var rem = need % (a.length-1); // remainder

     var sp = '';
     while (add-- > 0) sp += ' ';
     // replace
     var i,res = ''; // result
     for (i=0 ; i<a.length-1 ; i++) {
          res += a[i] + sp;
          if (rem-- > 0) res += ' '; // remainder
     }
     res += a[i];

     s = res;
}
console.log("'" + s + "' is " + s.length + " chars long.");

Upvotes: 1

Fabricator
Fabricator

Reputation: 12772

I think it's more efficient to compute the number spaces required in the beginning.

var s = "today is a friday";
var totalLength = 40;
var tokens = s.split(/\s+/);
var noSpaceLength = s.replace(/\s+/g,'').length;
var minSpace = Math.floor((totalLength - noSpaceLength)/(tokens.length-1));
var remainder = (totalLength - noSpaceLength) % (tokens.length-1);

var out = tokens[0];
for (var i = 1; i < tokens.length; i++) {
  var spaces = (i <= remainder ? minSpace+1 : minSpace);
  out += "-".repeat(spaces) + tokens[i];
}

$('#out').text(out);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="out"></div>

Upvotes: 1

Related Questions