Was ist die kanonische Methode, um eine Zeichenfolge in Ruby zu kürzen, ohne eine neue Zeichenfolge zu erstellen?


182

Das habe ich jetzt - was für die Arbeit, die es macht, zu ausführlich aussieht.

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

Angenommen, Token sind ein Array, das durch Teilen einer CSV-Zeile erhalten wird. jetzt die funktionen wie streifen! chomp! et. Alle geben null zurück, wenn die Zeichenfolge nicht geändert wurde

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

Was ist die Ruby-Methode, um es zu trimmen, wenn es zusätzliche führende oder nachfolgende Leerzeichen enthält, ohne Kopien zu erstellen?

Wird hässlicher, wenn ich will tokens[Title].chomp!.strip!


3
Wenn Sie wiederholt Dinge aus Token lesen, ist es möglicherweise sinnvoller, sie vorzuverarbeiten. Dh "tokens.each {| t | t.strip!}". dann kannst du einfach "@title = tokens [Title] || ''" machen
glenn mcdonald

Antworten:


272

Ich denke, was Sie wollen, ist:

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

Die #strip!Methode wird zurückgegebennil wenn nichts entfernt wurde, und die Variable selbst, wenn sie entfernt wurde.

Gemäß Ruby-Standards ändert eine Methode mit einem Ausrufezeichen die vorhandene Variable.

Hoffe das hilft.

Update: Dies wird ausgegeben irb, um zu demonstrieren:

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

1
Hmm .. trotzdem denke ich @title = tokens [Title] .strip! sieht sauberer aus - es ist schade, dass es anstelle der unveränderten Zeichenfolge null zurückgibt. Es sei denn, jemand schreibt eine bessere Antwort. Sie erhalten das akzeptierte Bit.
Gishu

7
Nun, @title = tokens [Title] .strip reicht aus, aber Sie hätten stattdessen eine Kopie, was in Ordnung ist, wenn Sie die Variable tokens [Title] unberührt lassen.
Igor

9
Ruby 1.9 verfügt über Tap, das genau das tut, was Sie wollen: @ title.tap {| x | x.strip!}
Timkay

2
@ Timkay Wäre es möglich zu tun @title.tap &:strip!? Das scheint sauberer als alles andere.
Jon Egeland

16
Warum in aller Welt würde es zurückkehren, nilwenn es nicht etwas abstreift? Das hat zweifellos eine Menge Leute verwirrt (da es keinen Sinn macht).
Josh M.

53

Übrigens, jetzt unterstützt Ruby schon nur Strip ohne "!".

Vergleichen Sie:

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

Auch ist es unmöglich, stripohne Duplikate. Siehe Quellen in 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 (30.10.2011) [i386-mingw32]

Update 1: Wie ich jetzt sehe - es wurde im Jahr 1999 erstellt (siehe Rev. 372 in SVN):

Update2: Es strip!werden keine Duplikate erstellt - sowohl in der Version 1.9.x, 2.x als auch in der Trunk-Version.


1
"Es ist unmöglich, ohne Duplikate zu strippen" - natürlich ist es möglich, dafür strip!ist es da.
Karoly Horvath

@KarolyHorvath sehen Sie nicht den Quellcode, geschrieben in C? Bitte lesen Sie sorgfältig, was ich hier über Duplikate geschrieben habe.
gaRex

1
Natürlich sehe ich es. Aber das ist der Quellcode von strip. Verstehe ich etwas falsch? Wie sonst könnte ich "unmöglich zu entfernen ohne Duplikat" interpretieren?
Karoly Horvath

@KarolyHorvath intern wird immer ein Duplikat erstellt. Das ist ungefähr String `str = rb_str_dup (str);`
gaRex

1
Und wenn Sie kein Duplikat möchten, verwenden Sie strip!aka rb_str_strip_bang.
Karoly Horvath

9

Strip und Chomp müssen nicht entfernt werden, da Strip auch nachfolgende Wagenrückläufe entfernt - es sei denn, Sie haben das Standardtrennzeichen für Datensätze geändert und das ist es, was Sie chompen.

Ollys Antwort hat bereits die kanonische Art, dies in Ruby zu tun. Wenn Sie dies jedoch häufig tun, können Sie jederzeit eine Methode dafür definieren:

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

Geben:

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

Beachten Sie auch, dass die if-Anweisung @titledie Zuweisung verhindert , wenn das Token Null ist, was dazu führt, dass der vorherige Wert beibehalten wird. Wenn Sie möchten oder nichts dagegen haben, @titleimmer zugewiesen zu werden, können Sie den Scheck in die Methode verschieben und die Duplizierung weiter reduzieren:

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

Wenn Sie sich abenteuerlustig fühlen, können Sie alternativ eine Methode für String selbst definieren:

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

Geben Sie eines von:

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

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

9

Wenn Sie Ruby on Rails verwenden, gibt es ein Quetschen

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

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

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

Wenn Sie nur Ruby verwenden, möchten Sie Strip verwenden

Hierin liegt die Gotcha. In Ihrem Fall möchten Sie Streifen ohne Knall verwenden!

während Strip! gibt sicherlich nil zurück, wenn es keine Aktion gab, aktualisiert es trotzdem die Variable, also Strip! kann nicht inline verwendet werden. Wenn Sie Strip Inline verwenden möchten, können Sie die Version ohne Knall verwenden!

Streifen! mit mehrzeiligem Ansatz

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

Strip Single Line Approach ... IHRE ANTWORT

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

4

Ich denke, Ihr Beispiel ist ein vernünftiger Ansatz, obwohl Sie es leicht vereinfachen könnten als:

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

Alternativ können Sie es in zwei Zeilen setzen:

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

3

Wenn Sie eine andere Methode verwenden möchten, nachdem Sie Folgendes benötigt haben:

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

Auf diese Weise kannst du dich ausziehen und trotzdem etwas tun :)


1

Meine Art:

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

1

Wenn Sie entweder Ruby 1.9 oder Activesupport haben, können Sie dies einfach tun

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

Das ist wirklich cool, da es meiner Meinung nach die :tryund die :tapMethode nutzt , die die mächtigsten funktionellen Konstrukte in Ruby sind.

Eine noch niedlichere Form, die als Symbole fungiert:

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

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

Es ist durchaus möglich, dass ich das Thema nicht verstehe, aber würde das nicht das tun, was Sie brauchen?

" success ".strip! || "rescue" #=> "success"
"failure".strip! || "rescue" #=> "rescue"
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.