【问题标题】:Truncate string when it is too long当字符串太长时截断字符串
【发布时间】:2013-09-27 09:11:39
【问题描述】:

我有两个字符串:

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

我想将print 的默认行为更改为:

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

long_string 仅部分打印。我尝试更改String#to_s,但没有成功。有谁知道这样怎么做?

更新

其实我希望它运行顺利,这意味着以下情况也可以正常运行:

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

所以我认为该行为属于字符串。

还是谢谢大家。

【问题讨论】:

    标签: ruby string


    【解决方案1】:

    首先,你需要一个方法来truncate一个字符串,比如:

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

    或者通过扩展String:(不过不建议更改核心类)

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

    现在您可以在打印字符串时调用truncate:

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

    或者你可以定义你自己的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, ...
    

    请注意,Kernel#puts 采用可变数量的参数,您可能需要相应地更改您的 puts 方法。

    【讨论】:

    • 如果字符串接近最大值,则省略号会将其覆盖。你需要类似:string.length > max ? "#{string[0...(max-3)]}..." : string,也许
    • 也可以使用省略号 (...) 而不是三个 .s 来保存另外 2 个字符,这样您就可以保留尽可能多的信息
    【解决方案2】:

    这就是Ruby on Rails 在他们的String#truncate 方法中作为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
    

    那你就可以这样使用了

    'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
    # => "And they f... (continued)"
    

    【讨论】:

      【解决方案3】:

      您可以围绕 puts 编写一个包装器,为您处理截断:

      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
      

      【讨论】:

      • 它返回nil,这使得测试变得有点困难。它可能应该只返回一个截断的字符串。
      • 更新了答案以返回截断的字符串,正如@vgoff 建议的那样。
      • 你错过了一个下划线:truncated_string
      【解决方案4】:

      自然截断

      我想提出一个自然截断的解决方案。我爱上了Ruby on Rails 提供的String#truncate method。上面的@Oto Brglez 已经提到过。不幸的是,我无法为纯红宝石重写它。所以我写了这个函数。

      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
      

      示例

      • 测试:我是一个示例短语,用于显示此函数的结果。
      • NOT:I am a sample phrase to show the result of the th...
      • 但是:我是一个示例短语,用于显示...的结果。

      注意:我对改进持开放态度,因为我确信可能存在更短的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-30
        • 1970-01-01
        • 2015-07-08
        • 2015-03-12
        相关资源
        最近更新 更多