Каков канонический способ обрезки строки в Ruby без создания новой строки?

Это то, что у меня есть сейчас - что выглядит слишком многословным для работы, которую он делает.

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

предположим, что токены-это массив, полученный путем разделения строки CSV. теперь функции, такие как strip! чомп! и. все вернет nil, если строка не была изменена

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

что Рубин так сказать обрезать его, если он содержит лишние пробелы без создания копий?

становится уродливее, если я хочу сделать tokens[Title].chomp!.strip!

9 ответов


Я думаю, что вы хотите это:

@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"

кстати, теперь ruby уже поддерживает только полосу без "!".

сравниваем:

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

также невозможно strip без дубликатов. См. источники в строке.с:

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 году (см. rev #372 в SVN):

обновление 2: strip! не будет создавать дубликаты - как в 1.9.x, 2.X и багажник версии.


нет необходимости как полосы, так и chomp, поскольку полоса также удалит возврат задней каретки - если вы не изменили разделитель записей по умолчанию, и это то, что вы жуете.

ответ Олли уже имеет канонический способ сделать это в Ruby, хотя, если вы обнаружите, что делаете это много, вы всегда можете определить метод для него:

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

даем:

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

также имейте в виду, что оператор if предотвратит @title от назначается, если токен равен нулю, что приведет к сохранению его предыдущего значения. Если вы хотите или не возражаете @title всегда назначается вы можете переместить проверку в метод и дополнительно уменьшить дублирование:

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

в качестве альтернативы, если вы чувствуете себя предприимчивыми, вы можете определить метод на себе строку:

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!

Если вы используете Ruby on Rails, есть хлюпать

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

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

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

Если вы используете только Ruby, вы хотите использовать прокладки

Здесь лежит gotcha.. в вашем случае вы хотите использовать полосы без взрыва !

в то время как полосы! конечно, возвращает nil, если не было никаких действий, он по-прежнему обновляет переменную so strip! невозможно использовать inline. Если вы хотите использовать strip inline, вы можете использовать версию без взрыва !

ленту! использование многострочного подхода

> 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"

Я думаю, что ваш пример-разумный подход, хотя вы могли бы немного упростить его как:

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

альтернатива вы можете поставить его на две строки:

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

Если вы хотите использовать другой метод после того, как вам понадобится что-то вроде этого:

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

таким образом, вы можете раздеться и все еще делать что-то после :)


мой путь:

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

если у вас есть ruby 1.9 или activesupport, вы можете сделать просто

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

Это очень круто, так как он использует :try и :tap метод, которые являются самыми мощными функциональными конструкциями в ruby, на мой взгляд.

еще более симпатичная форма, передающая функции как символы в целом:

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

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

вполне возможно, что я не понимаю тему, но разве это не сделает то, что вам нужно?

" success ".strip! || "rescue" #=> "success"
"failure".strip! || "rescue" #=> "rescue"