Quelle est la manière canonique de découper une chaîne dans Ruby sans créer de nouvelle chaîne?

C’est ce que j’ai maintenant – qui semble trop verbeux pour le travail qu’il effectue.

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

Supposons que les jetons sont un tableau obtenu en divisant une ligne CSV. maintenant les fonctions comme la bande! chomp! et. tout retourne nul si la chaîne n’a pas été modifiée

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

Quelle est la manière de dire Ruby de la couper si elle contient des espaces de début ou de fin supplémentaires sans créer de copies?

Obtient plus laid si je veux faire des tokens[Title].chomp!.ssortingp!

Je suppose que ce que vous voulez, c’est:

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

La #ssortingp! La méthode retournera nil si elle n’a rien enlevé, et la variable elle-même si elle a été supprimée.

Selon les normes Ruby, une méthode avec un point d’exclamation modifie la variable en place.

J’espère que cela t’aides.

Mise à jour: Ceci est irb de irb pour démontrer:

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

Au fait, Ruby prend déjà en charge la bande sans “!”.

Comparer:

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

Il est également impossible de se ssortingp sans doublons. Voir les sources dans ssortingng.c:

 static VALUE rb_str_ssortingp(VALUE str) { str = rb_str_dup(str); rb_str_ssortingp_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 année (voir rev # 372 dans SVN):

Update2: ssortingp! ne créera pas de doublons – à la fois dans les versions 1.9.x, 2.x et trunk.

Il n’est pas nécessaire à la fois de supprimer et de chomp comme la bande supprimera également les retours à la ligne de fin – à moins que vous ayez changé le séparateur d’enregistrement par défaut et que c’est ce que vous chomping.

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

 def ssortingp_or_self!(str) str.ssortingp! || str end 

Donnant:

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

Gardez également à l’esprit que l’instruction if empêchera @title d’être affectée si le jeton est nul, ce qui lui permet de conserver sa valeur précédente. Si vous ne voulez pas que @title toujours affecté, vous pouvez déplacer la vérification dans la méthode et réduire davantage la duplication:

 def ssortingp_or_self!(str) str.ssortingp! || str if str end 

Comme alternative, si vous vous sentez aventureux, vous pouvez définir une méthode sur Ssortingng lui-même:

 class Ssortingng def ssortingp_or_self! ssortingp! || self end end 

Donner l’un des:

 @title = tokens[Title].ssortingp_or_self! if tokens[Title] @title = tokens[Title] && tokens[Title].ssortingp_or_self! 

Si vous utilisez Ruby on Rails, il y a un squish

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

Si vous utilisez juste Ruby, vous voulez utiliser la bande

Ici se trouve le gotcha .. dans votre cas, vous voulez utiliser ssortingp sans le bang!

tout en bande! certainement retourne nul s’il n’y avait pas d’action, il met toujours à jour la variable afin de dépouiller! ne peut pas être utilisé en ligne. Si vous voulez utiliser la bande en ligne, vous pouvez utiliser la version sans le bang!

bande! en utilisant l’approche multi-lignes

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

dépouillez une seule ligne … VOTRE RÉPONSE

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

Je pense que votre exemple est une approche judicieuse, même si vous pouvez la simplifier légèrement comme suit:

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

Alternative, vous pouvez le mettre sur deux lignes:

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

Ma façon:

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

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

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

De cette façon, vous pouvez vous déshabiller et faire encore quelque chose après 🙂

Si vous avez Ruby 1.9 ou ActiveSupport, vous pouvez faire simplement

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

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

Une forme encore plus mignonne, en passant des fonctions comme des symboles:

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

Il est tout à fait possible que je ne comprenne pas le sujet, mais cela ne ferait-il pas ce dont vous avez besoin?

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