Truncate string when it is too long
Asked Answered
D

6

20

I have two strings:

short_string = "hello world"
long_string = "this is a very long long long .... string" # suppose more than 10000 chars

I want to change the default behavior of print to:

puts short_string
# => "hello world"
puts long_string
# => "this is a very long long....."

The long_string is only partially printed. I tried to change String#to_s, but it didn't work. Does anyone know how to do it like this?

updated

Actually i wanna it works smoothly, that means the following cases also work fine:

> puts very_long_str
> puts [very_long_str]
> puts {:a => very_long_str}

So i think the behavior belongs to String.

Thanks all anyway.

Doane answered 27/9, 2013 at 9:11 Comment(0)
W
25

First of all, you need a method to truncate a string, either something like:

def truncate(string, max)
  string.length > max ? "#{string[0...max]}..." : string
end

Or by extending String: (it's not recommended to alter core classes, though)

class String
  def truncate(max)
    length > max ? "#{self[0...max]}..." : self
  end
end

Now you can call truncate when printing the string:

puts "short string".truncate
#=> short string

puts "a very, very, very, very long string".truncate
#=> a very, very, very, ...

Or you could just define your own puts:

def puts(string)
  super(string.truncate(20))
end

puts "short string"
#=> short string

puts "a very, very, very, very long string"
#=> a very, very, very, ...

Note that Kernel#puts takes a variable number of arguments, you might want to change your puts method accordingly.

Willy answered 27/9, 2013 at 10:32 Comment(2)
If the string is nearly at max, then the ellipsis will put it over. You need something like: string.length > max ? "#{string[0...(max-3)]}..." : string, maybeDongdonga
Can also use the elipsis character (…) instead of three .s to save 2 more chars so you can retain as much info as possibleOrlosky
N
15

This is how Ruby on Rails does it in their String#truncate method as a monkey-patch:

class String
  def truncate(truncate_at, options = {})
    return dup unless length > truncate_at

    options[:omission] ||= '...'
    length_with_room_for_omission = truncate_at - options[:omission].length
    stop = if options[:separator]
      rindex(options[:separator], length_with_room_for_omission) || 
        length_with_room_for_omission
      else
        length_with_room_for_omission
      end

    "#{self[0...stop]}#{options[:omission]}"
  end
end

Then you can use it like this

'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
# => "And they f... (continued)"
Nitrogenous answered 27/9, 2013 at 9:29 Comment(0)
B
3

You can write a wrapper around puts that handles truncation for you:

def pleasant(string, length = 32)
  raise 'Pleasant: Length should be greater than 3' unless length > 3

  truncated_string = string.to_s
  if truncated_string.length > length
    truncated_string = truncated_string[0...(length - 3)]
    truncated_string += '...'
  end

  puts truncated_string
  truncated_string
end
Bride answered 27/9, 2013 at 9:31 Comment(3)
It returns nil which makes it a little harder to test. It should probably just return a truncated string.Ns
Updated answer to return the truncated string, as @Ns suggested.Bride
You missed an underscore though: truncated_stringFrasco
H
3

You can just use this syntax:

"mystring"[0..MAX_LENGTH]

[5] pry(main)> "hello world"[0..10]
=> "hello world"
[6] pry(main)> "hello world why"[0..10]
=> "hello world"
[7] pry(main)> "hello"[0..10]
=> "hello"

There's no need to check if it actually exceed the maximum length.

Higgs answered 19/9, 2022 at 12:23 Comment(0)
W
2

Truncate naturally

I want to propose a solution that truncates naturally. I fell in love with the String#truncate method offered by Ruby on Rails. It was already mentioned by @Oto Brglez above. Unfortunately I couldn't rewrite it for pure ruby. So I wrote this function.

def truncate(content, max)    
    if content.length > max
        truncated = ""
        collector = ""
        content = content.split(" ")
        content.each do |word|
            word = word + " " 
            collector << word
            truncated << word if collector.length < max
        end
        truncated = truncated.strip.chomp(",").concat("...")
    else
        truncated = content
    end
    return truncated
end

Example

  • Test: I am a sample phrase to show the result of this function.
  • NOT: I am a sample phrase to show the result of th...
  • BUT: I am a sample phrase to show the result of...

Note: I'm open for improvements because I'm convinced that there is a shorter solution possible.

Wilow answered 27/12, 2017 at 0:34 Comment(0)
R
0

You can use the truncate gem for this:

require 'truncate'
long_string = "this is a very long long long long long long long long"
puts long_string.truncate
Rigorous answered 4/7 at 4:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.