在Ruby中修剪字符串而不创建新字符串的规范方法是什么?


182

这就是我现在所拥有的-对于正在执行的工作,它看起来太冗长。

@title        = tokens[Title].strip! || tokens[Title] if !tokens[Title].nil?

假设令牌是通过拆分CSV行获得的数组。现在功能像条!mp!等。如果未修改字符串,则全部返回nil

"abc".strip!    # => nil
" abc ".strip!  # => "abc"

如果Ruby包含多余的前导或尾随空格而不创建副本,那么用Ruby修剪的方式是什么?

如果我想做的话会变得更丑 tokens[Title].chomp!.strip!


3
如果您要反复从令牌中读取内容,则对其进行预处理可能更有意义。即,“ tokens.each {| t | t.strip!}”。那么您只需执行“ @title = tokens [Title] ||”
glenn mcdonald

Answers:


272

我想你想要的是:

@title = tokens[Title]
@title.strip!

如果没有剥离任何内容,该#strip!方法将返回;nil如果剥离了该变量,则该方法本身将返回。

根据Ruby标准,后缀带有感叹号的方法会将变量更改到位。

希望这可以帮助。

更新:这是从输出irb来演示:

>> @title = "abc"
=> "abc"
>> @title.strip!
=> nil
>> @title
=> "abc"
>> @title = " abc "
=> " abc "
>> @title.strip!
=> "abc"
>> @title
=> "abc"

1
嗯..我还是觉得@title = tokens [Title] .strip!看起来更干净-可惜它返回nil而不是未修改的字符串。除非有人发布更好的答案,否则您将获得认可。
Gishu 2009年

7
好吧,@title = tokens [Title] .strip可以解决这个问题,但是您可以拥有一个副本,如果不更改tokens [Title]变量,这很好。
伊戈尔

9
Ruby 1.9具有水龙头功能,它完全可以满足您的需求:@ title.tap {| x | x.strip!}
timkay 2011年

2
@timkay可以做@title.tap &:strip!吗?看起来比其他任何东西都干净。
乔恩·埃格兰

16
为什么世界上它会返回,nil除非它剥离了一些东西?毫无疑问,这使很多人感到困惑(因为这没有任何意义)。
2014年

53

顺便说一句,现在红宝石已经支持仅带“!”的剥离。

比较:

p "abc".strip! == " abc ".strip!  # false, because "abc".strip! will return nil
p "abc".strip == " abc ".strip    # true

同样,strip没有重复也是不可能的。请参阅string.c中的源代码:

static VALUE
rb_str_strip(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_strip_bang(str);
    return str;
}

红宝石1.9.3p0(2011-10-30)[i386-mingw32]

更新1:如我现在所见-它创建于1999年(请参阅SVN中的第372版):

Update2: strip!不会创建重复项-在1.9.x,2.x和主干版本中均如此。


1
“没有重复就不可能剥离”-当然有可能,这就是strip!目的。
卡洛里·霍瓦斯

@KarolyHorvath看不到用C语言编写的源代码吗?请仔细阅读,我在这里写的关于重复的内容。
gaRex 2015年

1
我当然知道了。但这是的源代码strip。我误会了吗?我还能如何解释“不可能进行重复复制”?
Karoly Horvath

始终会创建@KarolyHorvath内部重复。那是关于字符串`str = rb_str_dup(str);`
gaRex 2015年

1
如果您不希望重复,可以使用strip!aka rb_str_strip_bang
Karoly Horvath

9

无需同时剥离和压缩,剥离也将删除尾随的回车符-除非您更改了默认的记录分隔符,这就是您要压缩的东西。

Olly的答案已经有了在Ruby中执行此操作的规范方法,尽管如果您发现自己经常执行此操作,则始终可以为其定义一个方法:

def strip_or_self!(str)
  str.strip! || str
end

给予:

@title = strip_or_self!(tokens[Title]) if tokens[Title]

还请记住,如果@title令牌为nil,则if语句将阻止分配,这将导致其保留其先前的值。如果您希望或不介意@title总是被分配,则可以将检查移到方法中,并进一步减少重复:

def strip_or_self!(str)
  str.strip! || str if str
end

或者,如果您喜欢冒险,可以在String本身上定义一个方法:

class String
  def strip_or_self!
    strip! || self
  end
end

提供以下之一:

@title = tokens[Title].strip_or_self! if tokens[Title]

@title = tokens[Title] && tokens[Title].strip_or_self!

9

如果您使用的是Ruby on Rails,则会有一些挤压

> @title = " abc "
 => " abc " 

> @title.squish
 => "abc"
> @title
 => " abc "

> @title.squish!
 => "abc"
> @title
 => "abc" 

如果仅使用Ruby,则要使用strip

陷阱就在这里。在您的情况下,您想使用没有爆炸的地带!

一会儿!当然,如果没有任何动作,它确实会返回nil,但它仍然会更新变量,因此删除!不能内联使用。如果要使用带内联,则可以使用没有爆炸声的版本!

跳闸!使用多行方法

> tokens["Title"] = " abc "
 => " abc "
> tokens["Title"].strip!
 => "abc"
> @title = tokens["Title"]
 => "abc"

单线方法...您的答案

> tokens["Title"] = " abc "
 => " abc "
> @title = tokens["Title"].strip if tokens["Title"].present?
 => "abc"

4

我认为您的示例是一个明智的方法,尽管您可以将其简化为:

@title = tokens[Title].strip! || tokens[Title] if tokens[Title]

或者,您可以将其放在两行中:

@title = tokens[Title] || ''
@title.strip!

3

如果您需要使用类似下面的方法的其他方法:

( str.strip || str ).split(',')

这样,您可以剥离并在之后仍然做一些事情:)


1

我的方式:

> (@title = " abc ").strip!
 => "abc" 
> @title
 => "abc" 

1

如果您有ruby 1.9或activesupport,则只需

@title = tokens[Title].try :tap, &:strip!

我觉得这很酷,因为它利用了:try:tap方法,这是ruby中最强大的功能构造。

更加可爱的形式,传递的功能完全是符号:

@title = tokens[Title].send :try, :tap, &:strip!

-1
@title = tokens[Title].strip! || tokens[Title]

我完全可能不理解该主题,但这是否可以满足您的需求?

" success ".strip! || "rescue" #=> "success"
"failure".strip! || "rescue" #=> "rescue"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.