Каков канонический способ обрезки строки в Ruby без создания новой строки? - PullRequest
173 голосов
/ 16 июня 2009

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

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

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

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

Как Ruby может сказать обрезать его, если он содержит дополнительные начальные или конечные пробелы без создания копий?

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

Ответы [ 9 ]

253 голосов
/ 16 июня 2009

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

@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"
50 голосов
/ 08 апреля 2012

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

Сравнить:

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;
}

ruby ​​1.9.3p0 (2011-10-30) [i386-mingw32]

Обновление 1: Как я вижу сейчас - он был создан в 1999 году (см. rev # 372 в SVN):

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

8 голосов
/ 16 июня 2009

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

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

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

Предоставление:

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

Также следует помнить, что оператор if будет препятствовать назначению @title, если токен равен nil, что приведет к тому, что он сохранит свое предыдущее значение. Если вы хотите или не возражаете против всегда назначаемого @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!
7 голосов
/ 28 октября 2015

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

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

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

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

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

В этом и заключается гоча .. в вашем случае вы хотите использовать полосу без взрыва!

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

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

> 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"
2 голосов
/ 01 декабря 2015

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

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

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

2 голосов
/ 16 июня 2009

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

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

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

@title = tokens[Title] || ''
@title.strip!
1 голос
/ 16 ноября 2013

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

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

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

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

@title = tokens[Title].send :try, :tap, &:strip!
1 голос
/ 08 апреля 2012

Мой путь:

> (@title = " abc ").strip!
 => "abc" 
> @title
 => "abc" 
0 голосов
/ 30 октября 2013
@title = tokens[Title].strip! || tokens[Title]

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

" success ".strip! || "rescue" #=> "success"
"failure".strip! || "rescue" #=> "rescue"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...