Ruby:子字符串到一定长度,并在子字符串中最后一个空格

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9503554/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:50:28  来源:igfitidea点击:

Ruby: substring to a certain length and also to last whitespace within substring

rubystringruby-on-rails-4

提问by e_r

I am trying to truncate a long string of text to a certain length, but want to also make sure that the truncated result ends at a whitespace. I am also going to append an ellipsis afterwards.

我试图将一长串文本截断到一定长度,但还想确保截断的结果以空格结尾。之后我还将附加一个省略号。

For example this:

例如这个:

"This is a very long string that has more characters than I want in it."

becomes this:

变成这样:

"This is a very long string that..."

I am starting with this but obviously this doesn't deal with the problem of ending the string on whitespace.

我从这个开始,但显然这并没有处理以空格结束字符串的问题。

<%= item.description[0..30] %>&hellip;

回答by evfwcqcg

s[0..30].gsub(/\s\w+\s*$/, '...')

The original answer didn't work in the case where the 30 character substring ended on a whitespace character. This solves that.

在 30 个字符的子字符串以空白字符结尾的情况下,原始答案不起作用。这就解决了。

>> desc="This is some text it is really long"

>> desc[0..30].gsub(/\s\w+$/,'...')
"This is some text it is really "

>> desc[0..30].gsub(/\s\w+\s*$/,'...')
"This is some text it is..."

回答by Jordan Running

If you're using Rails 4+ you should just use the built-in truncatehelper method, e.g.:

如果您使用的是 Rails 4+,您应该只使用内置的truncate辅助方法,例如:

<%= truncate item.description, length: 30, separator: /\w+/ %>

The string "…" will be appended to truncated text; to specify a different string, use the :omissionoption, e.g. omission: "xxx".

字符串“...”将被附加到截断的文本;要指定不同的字符串,请使用:omission选项,例如omission: "xxx".

For Rails 3.x the :separatoroption must be a string. Giving :separator => " "will be fine in many cases, but only catches spaces and not other whitespace. One compromise would be to use String#squish, which replaces all sequences of whitespace with a single space (and also trims leading and trailing whitespace), e.g. "foo\n\tbar ".squishyields "foo bar". It would look like this:

对于 Rails 3.x,:separator选项必须是字符串。:separator => " "在许多情况下,给予会很好,但只能捕获空格而不是其他空格。一种折衷方法是使用String#squish,它将所有空格序列替换为一个空格(并修剪前导和尾随空格),例如"foo\n\tbar ".squishyields "foo bar"。它看起来像这样:

<%= truncate item.description.squish, :length => 30, :separator => /\w/,
                                      :omission => "&hellip;" %>

回答by roychri

@evfwcqcg's answer is very good. I found it did not work well when

@evfwcqcg 的回答非常好。我发现它不工作的时候

  1. The string contained other characters that are non-space not alphanumerical.
  2. The string is shorter than the desired length.
  1. 该字符串包含非空格而非字母数字的其他字符。
  2. 字符串比所需的长度短。

Demonstration:

示范:

>> s = "How about we put some ruby method Class#Method in our string"
=> "How about we put some ruby method Class#Method in our string"
>> s[0..41].gsub(/\s\w+\s*$/, '...')
=> "How about we put some ruby method Class#Me"
>> s[0..999].gsub(/\s\w+\s*$/, '...')
=> "How about we put some ruby method Class#Method in our..."

This is not what I expected.

这不是我所期望的。

Here is what I am using to fix this:

这是我用来解决此问题的方法:

def truncate s, length = 30, ellipsis = '...'
  if s.length > length
    s.to_s[0..length].gsub(/[^\w]\w+\s*$/, ellipsis)
  else
    s
  end
end

When doing tests, here is the output:

进行测试时,输出如下:

>> s = "This is some text it is really long"
=> "This is some text it is really long"
>> truncate s
=> "This is some text it is..."

Still behave as expected.

仍然按预期行事。

>> s = "How about we put some ruby method Class#Method in our string"
=> "How about we put some ruby method Class#Method in our string"
>> truncate s, 41
=> "How about we put some ruby method Class..."
>> truncate s, 999
=> "How about we put some ruby method Class#Method in our string"

This is more like it.

这是更喜欢它。

回答by Ethan

desc.gsub(/([\w\s]{30}).+/,'...')

Expanding on the answer by @evfwcqcg, this is a pure regex that solves the problem of trailing whitespace.

扩展@evfwcqcg 的答案,这是一个解决尾随空格问题的纯正则表达式。

irb(main):031:0> desc="This is some text it is really long"
irb(main):033:0> desc.gsub(/([\w\s]{30}).+/,'...')
=> "This is some text it is really..."
irb(main):034:0> desc="This is some text it is really"
=> "This is some text it is really"
irb(main):035:0> desc.gsub(/([\w\s]{30}).+/,'...')
=> "This is some text it is really"
irb(main):036:0> desc="This is some text it is real"
=> "This is some text it is real"
irb(main):037:0> desc.gsub(/([\w\s]{30}).+/,'...')
=> "This is some text it is real"

回答by gorn

I am surprised that none of the answers is really correct (or limited by using rails helper) although this is very old question, so here is the solution.

我很惊讶没有一个答案是真正正确的(或受到使用 rails helper 的限制),尽管这是一个非常古老的问题,所以这里是解决方案。

Lets clearly formulate what it the goal first. We want truncate string sto 30 characters and cut the last word out as well if it can not entirely fit in. We also want to truncate trailing spaces from the result and add ellipsis, if the text was shortened.

让我们首先明确制定目标。我们希望将字符串截断s为 30 个字符,如果最后一个单词不能完全容纳,我们还希望将其删除。如果文本被缩短,我们还希望从结果中截断尾随空格并添加省略号。

If the text is longer then limit, than the shortening is as easy as

如果文本比限制更长,那么缩短就像

s[0,s.rindex(/\s/,30)].rstrip + '...'

If we wanted the entire result to be max 30 characters, than it is as simple as subtracting the length of ellipse from 30. So because we use three dots (and not one three-dot character) than we need

如果我们希望整个结果最多包含 30 个字符,那么就像从 30 中减去椭圆的长度一样简单。所以因为我们使用三个点(而不是一个三点字符)比我们需要的

s[0,s.rindex(/\s/,27)].rstrip + '...'

And the final result (with the test whether we need to truncate at all) is:

最终结果(测试我们是否需要截断)是:

if s.length<=30
  s
else
  s[0,s.rindex(/\s/,27)].rstrip + '...'
end

Thats it.

就是这样。



Note: There are some shady cases, when the desired result is not obvious. Here they are:

注意:有一些阴暗的情况,当所需的结果不明显时。他们来了:

  • If the string ends with lots of spaces (s= "Helo word ") but is shorter than 30. Should the spaces be preserved? - Currently they are.
  • The same as above, but the spaces at the end cross the limit o 30. Like in (s= "Twentyseven chars long text ") - Currently all spaces ad the end are truncated and ellipsis added.
  • 如果字符串以很多空格 ( s= "Helo word ")结尾,但长度小于 30。空格应该保留吗?- 目前他们是。
  • 与上面相同,但末尾的空格超过了 30 的限制。就像在 ( s= "Twentyseven chars long text ") 中一样 - 目前所有的空格都被截断并添加了省略号。

回答by user664833

class String
  def trunca(length=100, ellipsis='...')
    self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip
  end
end

Example:

例子:

-bash> irb
2.0.0p247 :001 > class String
2.0.0p247 :002?>     def trunca(length=100, ellipsis='...')
2.0.0p247 :003?>         self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip
2.0.0p247 :004?>       end
2.0.0p247 :005?>   end
 => nil 
2.0.0p247 :006 > s = "This is a very long string that has more characters than I want to display."
 => "This is a very long string that has more characters than I want to display." 
2.0.0p247 :007 > s.trunca(20)
 => "This is a very long..." 
2.0.0p247 :008 > s.trunca(31)
 => "This is a very long string that..."