What's the best way to truncate a string to the first n words?
4 Answers
n = 3
str = "your long long input string or whatever"
str.split[0...n].join(' ')
=> "your long long"
str.split[0...n] # note that there are three dots, which excludes n
=> ["your", "long", "long"]

- 33,354
- 5
- 79
- 106
-
24
-
1
-
3@ZackXu Make sure you use the `...` range literal, not the `..` one. Three dots excludes the nth value. – user513951 May 15 '14 at 17:19
-
You're right about. I overlooked. Mea Cupla. For exactly this reason, I believe my solution below is better because it's more clear. – Zack Xu May 15 '14 at 21:26
-
1What about: `truncate(my_string, :length => 300, :separator => ' ')` 300 being the number of characters. You won't be able to choose the number of words but that's not so bad! – Nima Izadi Jul 23 '14 at 08:28
-
1shouldn't it be `my_string.truncate(300, separator: ' ')`? http://apidock.com/rails/String/truncate – Yo Ludke Jul 03 '15 at 12:57
You could do it like this:
s = "what's the best way to truncate a ruby string to the first n words?"
n = 6
trunc = s[/(\S+\s+){#{n}}/].strip
if you don't mind making a copy.
You could also apply Sawa's Improvement (wish I was still a mathematician, that would be a great name for a theorem) by adjusting the whitespace detection:
trunc = s[/(\s*\S+){#{n}}/]
If you have to deal with an n
that is greater than the number of words in s
then you could use this variant:
s[/(\S+(\s+)?){,#{n}}/].strip

- 1
- 1

- 426,620
- 70
- 833
- 800
-
4
-
1@sawa: You could put that (and your version of the `split` approach) down as an answer, improvements and clarifications of existing answers are worthwhile. – mu is too short Jun 04 '11 at 18:06
-
1@GiangNguyen: In that case you could use `s[/(\S+(\s+)?){,#{n}}/].strip`. – mu is too short Oct 31 '13 at 19:10
You can use str.split.first(n).join(' ')
with n being any number.
Contiguous white spaces in the original string are replaced with a single white space in the returned string.
For example, try this in irb:
>> a='apple orange pear banana pineaple grapes'
=> "apple orange pear banana pineaple grapes"
>> b=a.split.first(2).join(' ')
=> "apple orange"
This syntax is very clear (as it doesn't use regular expression, array slice by index). If you program in Ruby, you know that clarity is an important stylistic choice.
A shorthand for join
is *
So this syntax str.split.first(n) * ' '
is equivalent and shorter (more idiomatic, less clear for the uninitiated).
You can also use take
instead of first
so the following would do the same thing
a.split.take(2) * ' '

- 11,505
- 9
- 70
- 78
This could be following if it's from rails 4.2 (which has truncate_words)
string_given.squish.truncate_words(number_given, omission: "")

- 5,252
- 3
- 34
- 36