Skip to content Skip to sidebar Skip to footer

How Can I Split A Long String In Two At The Nth Space?

These strings may be long paragraphs, so I'm not sure it's best to split the entire string with a space delimiter. I'm trying to get, say, the first 10 words and wrap them in a spa

Solution 1:

Considering you are only going to be scanning at most about 100 chars (unless you have URIs or very long words) then scanning character by character is quite optimal. You could optimise this by using .indexOf() in certain places, but you'd loose what you gained in having to check for each different character that could terminate a sentence.

function spanomatic ( str, words ) {
  var i, l, c;
  for ( i=0, l=str.length; i<l; i++ ) {
    c = str.charAt(i);
    if ( c == ' ' ) {
      if ( words-- <= 0 ) {
        str = '<span>'+str.substring(0,i)+'</span>'+str.substring(i);
        break;
      }
    }
    else if ( ('?!.;:').indexOf(c) != -1 ) {
      str = '<span>'+str.substring(0,i)+'</span>'+str.substring(i);
      break;
    }
  }
  return str;
}

spanomatic ( 'Pass your string here', 9 );

(The above code assumes your text will always be correctly gramatically termintated (i.e. contain at least one of ?!.;:) - if not then it would be possible for a paragraph with less than 9 words to end up spanless. This could be fixed by a few changes however...)

note for future readers

If you're going for a 'super efficient' way of doing string searching avoid Regular Expressions (unless you really need their power). The accepted answer for this question is concise and nicely put together function - don't get me wrong - but it's about 70% slower than just scanning the string with a for loop (in my tests on FireFox & Chrome at least)... and that's even when comparing after moving the Regular Expression definitions outside of Bergi's function (i.e. using pre-compiled regexps rather than recreating them every time the function is called).

http://jsperf.com/compare-regexp-vs-char-scanning


Solution 2:

return string.replace(/.+?[,.?!]|.+$/, function(match, index, string){
    var words = match.split(/\s+/);
    words[ words.length<10 ? words.length-1 : 9 ] += '</span>';
    return '<span class="easing">' + words.join(" ");
});

This matches the first sentence-like thing (or the whole string - unless linebreaks), and wraps the first 10 words of it in that span. Works for both your sample inputs, but also on smaller ones. Returns the empty string for an empty string, change the regex to …|.*$ if you want an empty span.


Solution 3:

Here. It's a bit code-golfy though. Sorry.

$( 'p' ).html(function ( i, text ) {
    var re = /(.+?)\s/g, c = 0, res;   
    while ( res = re.exec( text ) ) if ( ++c === 10 || res[1].slice( -1 ) === '.' ) break;

    var p = re.lastIndex;
    return '<span class="easing">' + text.slice( 0, p ) + '</span>' + text.slice( p );  
});

Live demo: http://jsfiddle.net/3DaEV/


Solution 4:

How about this code:

var str = 'asda adsfadsf asdfadfadsf adsfsdafadf. adfadfadfad adfadfdaf adfadfadf adfadf \afsgasfggasfg SFGDFGDSFGH dfghdsghdgas hadghdagh';

var sentences = [], words = str.split(' ');
for (var i = 0; i < 9; i++) {
    if (words[i].lastIndexOf('.') !== -1) {
        sentences.push(words[i]);
        break;    
    } else {
        sentences.push(words[i]);
    }        
}

words.slice(sentences.length, words.length);


$('<span>' + sentences.join(' ') + '</span>').appendTo($('#log'));

I have it under fiddle so you can test. You would want to do this in a loop with the remainder of arr1.

Update:

If it's not just the full stop but also ?!:;etc. then create a RegExp and test instead of doing lastIndexOf('.')


Post a Comment for "How Can I Split A Long String In Two At The Nth Space?"