显示一定长度的字符串而不截断

Posted

技术标签:

【中文标题】显示一定长度的字符串而不截断【英文标题】:Show a string of certain length without truncating 【发布时间】:2019-12-17 19:10:31 【问题描述】:

我在 ruby​​ 中显示一个特定长度的字符串。一行中只能显示该字符串的 80 个字符。例如,如果字符串长度为 82,那么它将显示为 2 行,如果长度为 250,则字符串将显示为 5 行等,我想在空格而不是单词上分割。

我是新手,不知道怎么解决。

【问题讨论】:

如果n = str.size是字符串的长度,计算m, r = n.divmod(80),然后计算m.times |i| puts str[80*i, 80] ; puts str[-r..-1] if r > 0。见Integer#divmod 和String#[]。 你是否关心分割字符串——例如只在空格处?还是可以在中间某处拆分单词? 不,我只想在空格处分割单词 您应该编辑您的问题以将信息合并到您上面的评论中。 【参考方案1】:
def wrap(str, max_line_len)
  str.scan /(?<=\A| ).1,#max_line_len(?= |\z)/
end

str = "Little Miss Muffet she sat on her tuffet, eating her curds and whey. Along " + 
      "came a spider who sat down beside her and frightened Miss Muffet away."

         1         2         3    
123456789012345678901234567890123

puts wrap(str, 31)
Little Miss Muffet she sat on
her tuffet, eating her curds
and whey. Along came a spider
who sat down beside her and
frightened Miss Muffet away.

puts wrap(str, 32)
Little Miss Muffet she sat on
her tuffet, eating her curds and
whey. Along came a spider who
sat down beside her and
frightened Miss Muffet away.

puts wrap(str, 33)
Little Miss Muffet she sat on her
tuffet, eating her curds and
whey. Along came a spider who sat
down beside her and frightened
Miss Muffet away.

见String#scan。正则表达式为“1max_line_len 字符之间的匹配,紧接在字符串开头或空格之前,紧跟空格或字符串结尾”。 (?&lt;=\A| )正向的后视(?= |\z)正向的前瞻

【讨论】:

干净简洁,完美运行。即使我是正则表达式的笨蛋! :))【参考方案2】:

只是出于好奇:

loop.inject([[], input]) do |(acc, src)|
  if m = src[/.1,79(\s|\z)/]
    [acc << m, $']
  else
    break acc << src
  end
end

【讨论】:

+1 表示loop 返回一个枚举器。我以前没见过。作为一个枚举器***者,我已经把它藏起来了。 不应该是break acc,为什么是79而不是80 @CarySwoveland 79 因为包含尾随空格。 break acc 似乎是合法的,是的。在任何情况下扫描都做得更好:)【参考方案3】:

一个非常快速和肮脏的迭代版本:

max_chars = 80
text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.'

lines = []
words = text.split

while words.length > 0
  line = words.shift

  while words.first && (line.length + words.first.length + 1) <= max_chars
    line << " #words.shift" 
  end

  lines << line
end

lines.each  |line|  puts line 
#=> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
#   tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
#   vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
#   no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit
#   amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
#   labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam
#   et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
#   sanctus est Lorem ipsum dolor sit amet.

【讨论】:

为什么几乎没有人选择loop.inject 而不是这个需要在外部作用域中声明局部变量的while? :)【参考方案4】:

其他选项,不是那么干净,但是...

这个想法是找到空格的索引并用\n替换索引接近行长的空格。

所以,给定字符串strmax_len

delta = 0
(str + " ")
.each_char.with_index.with_object([])  |(c, i), o| o << i if c == " " # find the index of the spaces
.each_cons(2).with_object([]) do |(a, b), tmp| # select the index to be substituted
  if b > (tmp.size + 1) * max_len + delta
    tmp << a 
    delta = tmp.last - max_len * tmp.size + 1
  end
end.each  |i| str[i] = "\n"  # substitute

当行长接近max_len 时,现在str 具有\n。 这会改变原始字符串。

【讨论】:

以上是关于显示一定长度的字符串而不截断的主要内容,如果未能解决你的问题,请参考以下文章

字符串长度截断,但不允许截断单词

如何截断 DataFrame 列中字符串的长度?

sql 查询语句截断问题

sql怎么插入日期类型数据报将截断字符串或二进制数据

查看数据帧的内容时是不是可以截断输出?

如何将PHP中的字符串截断为最接近一定数量字符的单词?