web-dev-qa-db-fra.com

Quel est le moyen canonique de couper une chaîne dans Ruby sans créer de nouvelle chaîne?

C’est ce que j’ai maintenant - qui semble trop bavard pour le travail qu’il accomplit.

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

Supposons que les jetons sont un tableau obtenu en scindant une ligne CSV. maintenant les fonctions comme strip! chomp! et. tous renvoient nil si la chaîne n'a pas été modifiée

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

Quelle est la méthode Ruby pour dire de le rogner s'il contient des espaces de début ou de fin supplémentaires sans créer de copies?

Est plus laid si je veux faire tokens[Title].chomp!.strip!

175
Gishu

Je suppose que ce que tu veux c'est:

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

La méthode #strip! renverra nil si elle ne supprime rien et la variable elle-même si elle a été supprimée.

Selon les normes Ruby, une méthode suffixée d'un point d'exclamation modifie la variable en place.

J'espère que cela t'aides.

Update: Ceci est sorti de irb pour montrer:

_>> @title = "abc"
=> "abc"
>> @title.strip!
=> nil
>> @title
=> "abc"
>> @title = " abc "
=> " abc "
>> @title.strip!
=> "abc"
>> @title
=> "abc"
_
256
Igor

Btw, maintenant Ruby supporte déjà le strip sans "!".

Comparer:

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

De plus, il est impossible de strip sans doublons. Voir les sources dans 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]

Mise à jour 1: Comme je le vois maintenant - il a été créé en 1999 (voir rev # 372 dans SVN):

Update2: strip! ne créera pas de doublons - dans les versions 1.9.x, 2.x et trunk.

50
gaRex

Il n'est pas nécessaire à la fois strip et chomp, car strip supprimera également les retours à la fin du tableau - sauf si vous avez modifié le séparateur d'enregistrement par défaut et c'est ce que vous chompez.

La réponse d'Olly a déjà la manière canonique de faire cela en Ruby, bien que si vous le faites souvent, vous pouvez toujours définir une méthode pour cela:

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

Donnant:

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

N'oubliez pas non plus que l'instruction if empêchera que @title soit attribué si le jeton est nul, ce qui lui permettra de conserver sa valeur précédente. Si vous voulez ou que cela ne vous dérange pas que @title soit toujours affecté, vous pouvez déplacer le contrôle dans la méthode et réduire davantage la duplication:

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

Si vous vous sentez aventureux, vous pouvez également définir une méthode sur String lui-même:

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

Donner un de:

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

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

Si vous utilisez Ruby sur Rails il y a un squish

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

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

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

Si vous utilisez uniquement Ruby vous souhaitez utiliser strip

C’est là que se trouve le gotcha .. dans votre cas, vous voulez utiliser du strip sans le coup!

en bande! renvoie certainement nil s'il n'y a pas eu d'action, il met toujours à jour la variable alors strip! ne peut pas être utilisé en ligne. Si vous voulez utiliser strip inline, vous pouvez utiliser la version sans le bang!

strip! utilisant une approche multiligne

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

strip approche mono-ligne ... VOTRE RÉPONSE

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

Si vous souhaitez utiliser une autre méthode après avoir besoin de quelque chose comme ceci:

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

De cette façon, vous pouvez décaper et toujours faire quelque chose après :)

2

Je pense que votre exemple est une approche sensée, bien que vous puissiez le simplifier légèrement en:

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

Alternative vous pouvez le mettre sur deux lignes:

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

Mon chemin:

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

Si vous avez soit Ruby 1.9 ou actifupport, vous pouvez faire simplement

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

C’est vraiment cool, car il tire parti des méthodes :try et :tap, qui sont les constructions fonctionnelles les plus puissantes de Ruby, à mon avis.

Une forme encore plus mignonne, en passant, fonctionne comme un symbole:

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