Apa cara kanonik untuk memotong string di Ruby tanpa membuat string baru?

182

Inilah yang saya miliki sekarang - yang terlihat terlalu bertele-tele untuk pekerjaan yang dilakukannya.

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

Asumsikan token adalah array yang diperoleh dengan memisahkan garis CSV. sekarang fungsinya seperti strip! chomp! et. semua mengembalikan nihil jika string tidak dimodifikasi

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

Apa cara Ruby mengatakan trim jika itu berisi spasi tambahan tambahan atau spasi tambahan tanpa membuat salinan?

Akan lebih buruk jika saya ingin melakukannya tokens[Title].chomp!.strip!

Gishu
sumber
3
Jika Anda akan membaca hal-hal dari token berulang kali, mungkin lebih masuk akal untuk melakukan pra-proses. Yaitu, "token.each {| t | t.strip!}". maka Anda bisa melakukan "@title = token [Judul] || ''"
glenn mcdonald

Jawaban:

272

Saya kira yang Anda inginkan adalah:

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

The #strip!Metode akan kembali niljika tidak mengupas apa-apa, dan variabel itu sendiri jika ditelanjangi.

Menurut standar Ruby, metode yang diberi akhiran dengan tanda seru mengubah variabel yang ada.

Semoga ini membantu.

Pembaruan: Ini adalah output dari irbuntuk menunjukkan:

>> @title = "abc"
=> "abc"
>> @title.strip!
=> nil
>> @title
=> "abc"
>> @title = " abc "
=> " abc "
>> @title.strip!
=> "abc"
>> @title
=> "abc"
Igor
sumber
1
Hmm .. tetap saja saya rasa @title = token [Judul] .strip! terlihat lebih bersih - sayang ia mengembalikan nihil bukannya string yang tidak dimodifikasi. Kecuali seseorang memposting yang lebih baik .. Anda mendapatkan bit yang diterima.
Gishu
7
Nah, @title = token [Judul] .strip akan melakukan trik tetapi Anda akan memiliki salinannya, yang tidak masalah jika Anda menyimpan variabel token [Judul] tidak tersentuh.
Igor
9
Ruby 1.9 memiliki ketuk, yang melakukan persis apa yang Anda inginkan: @ title.tap {| x | x.strip!}
timkay
2
@timkay Apakah mungkin dilakukan @title.tap &:strip!? Tampaknya lebih bersih dari yang lainnya.
Jon Egeland
16
Mengapa di dunia ini akan kembali nilkecuali jika melucuti sesuatu? Itu tidak diragukan lagi membingungkan banyak orang (karena itu tidak masuk akal).
Josh M.
53

Btw, sekarang ruby ​​sudah mendukung hanya strip tanpa "!".

Membandingkan:

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

Juga tidak mungkin striptanpa duplikat. Lihat sumber di 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]

Pembaruan 1: Seperti yang saya lihat sekarang - itu dibuat pada tahun 1999 tahun (lihat rev # 372 di SVN):

Update2: strip!tidak akan membuat duplikat - keduanya dalam versi 1.9.x, 2.x dan trunk.

gaRex
sumber
1
"Tidak mungkin untuk stripping tanpa duplikat" - tentu saja itu mungkin, itulah gunanya strip!.
Karoly Horvath
@ KarolyHorvath jangan Anda melihat kode sumber, ditulis dalam C? Tolong baca dengan seksama, apa yang saya tulis di sini tentang duplikat.
gaRex
1
Tentu saja saya melihatnya. Tapi itu kode sumber strip. Apakah saya salah mengerti sesuatu? Bagaimana lagi saya bisa mengartikan "mustahil untuk stripping tanpa duplikat"?
Karoly Horvath
Duplikat internal @KarolyHorvath selalu dibuat. Itu tentang string `str = rb_str_dup (str);`
gaRex
1
Dan jika Anda tidak ingin duplikat, Anda menggunakan strip!alias rb_str_strip_bang.
Karoly Horvath
9

Tidak perlu kedua strip dan chomp sebagai strip juga akan menghapus pengembalian carriage trailing - kecuali Anda telah mengubah pemisah rekaman default dan itulah yang Anda chomping.

Jawaban Olly sudah memiliki cara kanonik untuk melakukan ini di Ruby, meskipun jika Anda sering melakukan ini, Anda selalu dapat menentukan metode untuk itu:

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

Memberi:

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

Juga perlu diingat bahwa pernyataan if akan mencegah @titlepenugasan jika token nihil, yang akan membuatnya mempertahankan nilai sebelumnya. Jika Anda ingin atau tidak keberatan @titleselalu ditugaskan, Anda dapat memindahkan cek ke dalam metode dan selanjutnya mengurangi duplikasi:

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

Sebagai alternatif, jika Anda ingin berpetualang, Anda dapat menentukan metode pada String itu sendiri:

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

Memberi salah satu dari:

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

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

sumber
9

Jika Anda menggunakan Ruby on Rails ada squish

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

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

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

Jika Anda hanya menggunakan Ruby, Anda ingin menggunakan strip

Di sinilah letak gotcha .. dalam kasus Anda, Anda ingin menggunakan strip tanpa bang!

saat telanjang! tentu saja mengembalikan nihil jika tidak ada tindakan itu masih memperbarui variabel jadi strip! tidak dapat digunakan inline. Jika Anda ingin menggunakan strip inline, Anda dapat menggunakan versi tanpa bang!

mengupas! menggunakan pendekatan multi-line

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

strip pendekatan jalur tunggal ... JAWABAN ANDA

> tokens["Title"] = " abc "
 => " abc "
> @title = tokens["Title"].strip if tokens["Title"].present?
 => "abc"
pintu gerbang
sumber
4

Saya pikir contoh Anda adalah pendekatan yang masuk akal, meskipun Anda dapat menyederhanakannya sedikit sebagai:

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

Alternatif Anda bisa meletakkannya di dua baris:

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

Jika Anda ingin menggunakan metode lain setelah Anda membutuhkan sesuatu seperti ini:

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

Dengan cara ini Anda dapat membuka dan masih melakukan sesuatu setelah :)

Diogo Neves - Mangaru
sumber
1

Jalanku:

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

Jika Anda memiliki ruby ​​1.9 atau support, Anda dapat melakukannya dengan mudah

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

Ini sangat keren, karena memanfaatkan :trydan :tapmetode, yang merupakan konstruksi fungsional paling kuat di ruby, menurut pendapat saya.

Bentuk yang lebih imut, yang berfungsi sebagai simbol sekaligus:

@title = tokens[Title].send :try, :tap, &:strip!
ditulis ulang
sumber
-1
@title = tokens[Title].strip! || tokens[Title]

Sangat mungkin saya tidak mengerti topik, tetapi tidakkah ini akan melakukan apa yang Anda butuhkan?

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