วิธีที่ง่ายที่สุดในการลบอักขระแรกจากสตริงคืออะไร


174

ตัวอย่าง:

[12,23,987,43

วิธีที่รวดเร็วและมีประสิทธิภาพที่สุดในการลบ " [" โดยใช้อาจเป็นchop()แต่สำหรับตัวอักษรตัวแรก


1
ฉันแก้ไขคำตอบของฉันดังนั้นอาจเป็นไปได้ที่จะเปลี่ยนคำตอบที่คุณเลือก ดูว่าคุณสามารถให้รางวัลกับคำตอบของ Jason Stirk หรือไม่เพราะเขาเป็นคนที่เร็วที่สุดและอ่านง่ายมาก
มนุษย์ดีบุก

3
ใช้ str [1 ..- 1] ซึ่งเร็วที่สุดตามคำตอบด้านล่าง
Achyut Rastogi

1
ในฐานะของทับทิม 2.5 คุณสามารถใช้delete_prefixและdelete_prefix!- รายละเอียดเพิ่มเติมด้านล่าง ฉันไม่มีเวลาในการเปรียบเทียบ แต่จะทำเร็ว ๆ นี้!
SRack

อัปเดต: ฉันเปรียบเทียบมาตรฐานใหม่ ( delete_prefix\ delete_prefix!) และพวกเขาก็ค่อนข้างเร็ว การทำความเร็วก่อนหน้านี้ไม่ได้เป็นเรื่องที่โปรดปราน แต่ความสามารถในการอ่านหมายความว่าเป็นตัวเลือกใหม่ที่ยอดเยี่ยม!
SRack

คำตอบ:


233

ฉันชอบใช้สิ่งที่ชอบ:

asdf = "[12,23,987,43"
asdf [0] = '' 

p asdf
# >> "12,23,987,43"

ฉันมักจะมองหาวิธีที่เร็วและอ่านง่ายที่สุดในการทำสิ่งต่าง ๆ :

require 'benchmark'

N = 1_000_000

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }

end

ทำงานบน Mac Pro ของฉัน:

1.9.3
              user     system      total        real
[0]       0.840000   0.000000   0.840000 (  0.847496)
sub       1.960000   0.010000   1.970000 (  1.962767)
gsub      4.350000   0.020000   4.370000 (  4.372801)
[1..-1]   0.710000   0.000000   0.710000 (  0.713366)
slice     1.020000   0.000000   1.020000 (  1.020336)
length    1.160000   0.000000   1.160000 (  1.157882)

การอัปเดตเพื่อรวมคำตอบที่แนะนำอีกหนึ่งข้อ:

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

ซึ่งผลลัพธ์ใน:

2.1.2
              user     system      total        real
[0]       0.300000   0.000000   0.300000 (  0.295054)
sub       0.630000   0.000000   0.630000 (  0.631870)
gsub      2.090000   0.000000   2.090000 (  2.094368)
[1..-1]   0.230000   0.010000   0.240000 (  0.232846)
slice     0.320000   0.000000   0.320000 (  0.320714)
length    0.340000   0.000000   0.340000 (  0.341918)
eat!      0.460000   0.000000   0.460000 (  0.452724)
reverse   0.400000   0.000000   0.400000 (  0.399465)

และอีกวิธีใช้/^./ในการค้นหาอักขระตัวแรก:

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('[/^./]') { N.times { "[12,23,987,43"[/^./] = '' } }
  b.report('[/^\[/]') { N.times { "[12,23,987,43"[/^\[/] = '' } }
  b.report('sub+') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[/, "") } }
  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

ซึ่งผลลัพธ์ใน:

# >> 2.1.5
# >>               user     system      total        real
# >> [0]       0.270000   0.000000   0.270000 (  0.270165)
# >> [/^./]    0.430000   0.000000   0.430000 (  0.432417)
# >> [/^\[/]   0.460000   0.000000   0.460000 (  0.458221)
# >> sub+      0.590000   0.000000   0.590000 (  0.590284)
# >> sub       0.590000   0.000000   0.590000 (  0.596366)
# >> gsub      1.880000   0.010000   1.890000 (  1.885892)
# >> [1..-1]   0.230000   0.000000   0.230000 (  0.223045)
# >> slice     0.300000   0.000000   0.300000 (  0.299175)
# >> length    0.320000   0.000000   0.320000 (  0.325841)
# >> eat!      0.410000   0.000000   0.410000 (  0.409306)
# >> reverse   0.390000   0.000000   0.390000 (  0.393044)

นี่คือการอัปเดตอื่น ๆ เกี่ยวกับฮาร์ดแวร์ที่เร็วขึ้นและ Ruby รุ่นใหม่กว่า:

2.3.1
              user     system      total        real
[0]       0.200000   0.000000   0.200000 (  0.204307)
[/^./]    0.390000   0.000000   0.390000 (  0.387527)
[/^\[/]   0.360000   0.000000   0.360000 (  0.360400)
sub+      0.490000   0.000000   0.490000 (  0.492083)
sub       0.480000   0.000000   0.480000 (  0.487862)
gsub      1.990000   0.000000   1.990000 (  1.988716)
[1..-1]   0.180000   0.000000   0.180000 (  0.181673)
slice     0.260000   0.000000   0.260000 (  0.266371)
length    0.270000   0.000000   0.270000 (  0.267651)
eat!      0.400000   0.010000   0.410000 (  0.398093)
reverse   0.340000   0.000000   0.340000 (  0.344077)

ทำไม gsub ถึงช้าจัง

หลังจากทำการค้นหา / แทนที่จะgsubต้องตรวจสอบการจับคู่เพิ่มเติมที่เป็นไปได้ก่อนที่จะสามารถบอกได้ว่ามันเสร็จแล้ว subทำเพียงหนึ่งและเสร็จสิ้น ลองคิดดูสิgsubว่ามันจะเป็นการsubโทรขั้นต่ำสองครั้ง

นอกจากนี้สิ่งสำคัญคือต้องจำไว้ว่าgsubและsubสามารถพิการได้ด้วย regex ที่เขียนไม่ดีซึ่งตรงกับช้ากว่าการค้นหาสตริงย่อย หากเป็นไปได้ให้ยึด regex เพื่อให้ได้ความเร็วสูงสุด มีคำตอบอยู่ที่ Stack Overflow ซึ่งแสดงให้เห็นดังนั้นหากคุณต้องการข้อมูลเพิ่มเติม


34
สิ่งสำคัญคือต้องทราบว่าจะใช้งานได้ใน Ruby 1.9 เท่านั้น ใน Ruby 1.8 สิ่งนี้จะลบไบต์แรกออกจากสตริงไม่ใช่อักขระตัวแรกซึ่งไม่ใช่สิ่งที่ OP ต้องการ
Jörg W Mittag

+1: ฉันมักจะลืมไปที่ตำแหน่งสตริงที่คุณสามารถกำหนดได้ไม่เพียง แต่ตัวละครเดียว แต่คุณยังสามารถแทรกสตริงย่อยได้ ขอบคุณ!
quetzalcoatl

"[12,23,987,43".delete "["
rupweb

4
นั่นเป็นการลบออกจากทุกตำแหน่งซึ่งไม่ใช่สิ่งที่ OP ต้องการ: "... สำหรับอักขระตัวแรก?"
คนดีบุก

2
" what about "[12,23,987,43".shift ?" แล้ว"[12,23,987,43".shift NoMethodError: undefined method กะสำหรับ "[12,23,987,43": String`
ชายดีบุก

293

คล้ายกับคำตอบของ Pablo ด้านบน แต่เป็นน้ำยาทำความสะอาดที่ร่ม:

str[1..-1]

จะส่งคืนอาร์เรย์ตั้งแต่ 1 ถึงอักขระสุดท้าย

'Hello World'[1..-1]
 => "ello World"

13
+1 ดูผลการเปรียบเทียบที่ฉันเพิ่มในคำตอบของฉัน คุณมีเวลาวิ่งเร็วที่สุดรวมทั้งฉันคิดว่ามันสะอาดมาก
มนุษย์ดีบุก

แล้วประสิทธิภาพของการstr[1,]เปรียบเทียบกับด้านบนล่ะ?
Bohr

1
@Bohr: str[1,]คุณกลับตัวละครที่ 2 1:nilตั้งแต่ช่วงคือ คุณต้องระบุความยาวที่คำนวณได้จริงหรือสิ่งที่รับประกันว่าจะสูงกว่าความยาวเช่นstr[1,999999](ใช้ int_max แน่นอน) เพื่อให้ได้ส่วนท้ายทั้งหมด [1..-1]สะอาดและอาจเร็วกว่าเนื่องจากคุณไม่จำเป็นต้องทำงานด้วยความยาวด้วยตนเอง (ดู [1..length] ตามเกณฑ์มาตรฐาน)
quetzalcoatl

4
ทางออกที่ดีมาก โดยวิธีการถ้าต้องการลบตัวอักษรแรกและตัวสุดท้าย:str[1..-2]
pisaruk

50

เราสามารถใช้ชิ้นเพื่อทำสิ่งนี้:

val = "abc"
 => "abc" 
val.slice!(0)
 => "a" 
val
 => "bc" 

การใช้slice!เราสามารถลบตัวอักษรใด ๆ โดยระบุดัชนีของมัน


2
slice!(0)คำตอบที่ได้รับการเลือกสรรมาอย่างดีเลิศนี้ควรจะใช้จริงๆในasdf[0] = '' การลบตัวละครตัวแรกนั้นไร้สาระ (เช่นการใช้ gsub กับ regex และยิงด้วยปืนครก)
f055

1
แม้ว่ามันอาจดูไม่คุ้นเคยบนพื้นผิว แต่[]=ก็ไม่ต้องการรหัส C พื้นฐานที่slice!จำเป็นต้องใช้งานเพิ่มเติม ที่เพิ่มขึ้น อาร์กิวเมนต์อาจเป็น "แบบใดที่สามารถอ่านได้มากกว่า" ฉันพบว่าใช้[]=อ่านได้ แต่ฉันมาจากพื้นหลัง C -> Perl ซึ่งอาจทำให้ความคิดของฉัน นักพัฒนา Java อาจจะคิดว่ามันอ่านน้อย ทั้งเป็นวิธีที่ยอมรับได้ในการทำงานให้สำเร็จตราบเท่าที่เข้าใจได้ง่ายและบำรุงรักษาได้และไม่โหลด CPU อย่างไม่เหมาะสม
Tin Man

ตกลง. คุณรู้วิธีที่เราสามารถวัดค่าได้หรือไม่ถ้าฟังก์ชั่นใช้โหลด CPU มากใน ROR หรือเราควรใช้ความแตกต่างของเวลาดำเนินการเป็นมิลลิวินาทีหรือไม่?
balanv

18

ทับทิม 2.5+

ในฐานะของ Ruby 2.5 คุณสามารถใช้delete_prefixหรือdelete_prefix!เพื่อให้บรรลุในลักษณะที่อ่านได้

ในกรณี"[12,23,987,43".delete_prefix("[")นี้

ข้อมูลเพิ่มเติมที่นี่:

'invisible'.delete_prefix('in') #=> "visible"
'pink'.delete_prefix('in') #=> "pink"

NB คุณยังสามารถใช้สิ่งนี้เพื่อลบรายการออกจากจุดสิ้นสุดของสตริงด้วยdelete_suffixและdelete_suffix!

'worked'.delete_suffix('ed') #=> "work"
'medical'.delete_suffix('ed') #=> "medical"

แก้ไข:

โดยใช้การตั้งค่ามาตรฐานดีบุกก็ดูสวยได้อย่างรวดเร็วเกินไป (ภายใต้สองรายการสุดท้ายdelete_pและdelete_p!) ไม่ได้ค่อนข้าง pip faves ก่อนหน้านี้สำหรับความเร็ว แต่สามารถอ่านได้มาก

2.5.0
              user     system      total        real
[0]       0.174766   0.000489   0.175255 (  0.180207)
[/^./]    0.318038   0.000510   0.318548 (  0.323679)
[/^\[/]   0.372645   0.001134   0.373779 (  0.379029)
sub+      0.460295   0.001510   0.461805 (  0.467279)
sub       0.498351   0.001534   0.499885 (  0.505729)
gsub      1.669837   0.005141   1.674978 (  1.682853)
[1..-1]   0.199840   0.000976   0.200816 (  0.205889)
slice     0.279661   0.000859   0.280520 (  0.285661)
length    0.268362   0.000310   0.268672 (  0.273829)
eat!      0.341715   0.000524   0.342239 (  0.347097)
reverse   0.335301   0.000588   0.335889 (  0.340965)
delete_p  0.222297   0.000832   0.223129 (  0.228455)
delete_p!  0.225798   0.000747   0.226545 (  0.231745)


14

หากคุณต้องการปลดเครื่องหมายนำหน้า:

"[12,23,987,43".gsub(/^\[/, "")

หากคุณต้องการลบอักขระแรกและคุณรู้ว่ามันจะไม่อยู่ในชุดอักขระหลายไบต์:

"[12,23,987,43"[1..-1]

หรือ

"[12,23,987,43".slice(1..-1)

1
ฉันต้องการใช้แทน"[12,23,987,43".sub(/^\[+/, "") gsub(/^\[/, "")ครั้งแรกที่ให้เอนจิ้น regex ค้นหาการแข่งขันทั้งหมดจากนั้นพวกเขาจะถูกแทนที่ในการกระทำหนึ่งและผลลัพธ์ในการปรับปรุงความเร็ว 2x ด้วย Ruby 1.9.3
มนุษย์ดีบุก

1
เนื่องจากเรากำลังจัดการกับสตริงสิ่งนี้ควรเป็นgsub(/\A\[/, "") อย่างไร
Sagar Pandya


4

ตัวอย่างเช่น: a = "One Two Three"

1.9.2-p290 > a = "One Two Three"
 => "One Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "ne Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "e Two Three" 

1.9.2-p290 > a = a[1..-1]
 => " Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "wo Three" 

ด้วยวิธีนี้คุณสามารถลบทีละตัวอักษรตัวแรกของสตริง


3
นี่เป็นเช่นเดียวกับคำตอบของ Jason Stirkเท่านั้นเขาถูกส่งมาหลายเดือนก่อน
คนดีบุก

3

ทางที่ง่าย:

str = "[12,23,987,43"

removed = str[1..str.length]

วิธีที่ยอดเยี่ยม:

class String
  def reverse_chop()
    self[1..self.length]
  end
end

"[12,23,987,43".reverse_chop()

(หมายเหตุ: ชอบวิธีที่ง่าย :))


1
หากคุณต้องการรักษาความหมาย "สับ" ที่คุณสามารถทำได้"[12,23,987,43".reverse.chop.reverse
Chris Heald

นั่นเป็นค่าใช้จ่ายในการแสดงครั้งใหญ่ที่จะดึงตัวละครตัวหนึ่งออกมา
Pablo Fernandez

7
ทำไมไม่ใช้ [1 ..- 1] มากกว่า [1..self.length]
horseyguy

ตัวอย่างการปะแก้ลิงนั้นค่อนข้างไม่ดีสำหรับคำถามนี้มันเป็นเพียง IMO ที่ไม่เกี่ยวข้องและน่าเกลียด
dredozubov

3

ขอบคุณ @ the-tin-man สำหรับการรวบรวมมาตรฐาน!

อนิจจาฉันไม่ชอบวิธีแก้ปัญหาเหล่านี้เลย พวกเขาต้องการขั้นตอนพิเศษเพื่อให้ได้ผลลัพธ์ ( [0] = '', .strip!) หรือพวกเขาไม่ได้มีความหมายมาก / ชัดเจนเกี่ยวกับสิ่งที่เกิดขึ้น ( [1..-1]: "อืมช่วงจาก 1 ถึงลบ 1? Yearg?") หรือช้าหรือยาวไป เขียน ( .gsub, .length)

สิ่งที่เราพยายามทำคือ 'shift' (ใน Array parlance) แต่คืนอักขระที่เหลือกลับคืนมาแทนที่จะเป็นสิ่งที่ถูกเลื่อนออกไป ลองใช้ Ruby ของเราเพื่อทำให้เป็นไปได้ด้วยสตริง! เราสามารถใช้การดำเนินการ bracket อย่างรวดเร็ว แต่ให้ชื่อที่ดีและใช้ arg เพื่อระบุจำนวนที่เราต้องการจะส่งออกไปด้านหน้า:

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

แต่มีอีกมากที่เราสามารถทำได้ด้วยการทำงานของฉากยึดที่รวดเร็ว แต่ไม่มั่นคง ในขณะที่เราอยู่ที่นั้นเพื่อความสมบูรณ์ลองเขียน a #shiftและ#firstสำหรับ String (ทำไม Array ควรมีความสนุกทั้งหมด) ให้การหาเรื่องเพื่อระบุจำนวนตัวอักษรที่เราต้องการลบตั้งแต่ต้น:

class String
  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

ตกลงตอนนี้เรามีวิธีที่ชัดเจนในการดึงอักขระออกจากด้านหน้าของสตริงด้วยวิธีการที่สอดคล้องกับArray#firstและArray#shift(ซึ่งควรจะเป็นวิธีการปัง ??) #eat!และเราสามารถได้รับการแก้ไขสตริงเป็นอย่างดีด้วย อืมเราควรแบ่งปันeat!พลังการผลิตใหม่ของเรากับ Array หรือไม่? ทำไมจะไม่ล่ะ!

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

ตอนนี้เราสามารถ:

> str = "[12,23,987,43" #=> "[12,23,987,43"
> str.eat!              #=> "12,23,987,43"
> str                   #=> "12,23,987,43"

> str.eat!(3)           #=> "23,987,43"
> str                   #=> "23,987,43"

> str.first(2)          #=> "23"
> str                   #=> "23,987,43"

> str.shift!(3)         #=> "23,"
> str                   #=> "987,43"

> arr = [1,2,3,4,5]     #=> [1, 2, 3, 4, 5] 
> arr.eat!              #=> [2, 3, 4, 5] 
> arr                   #=> [2, 3, 4, 5] 

นั่นดีกว่า!


2
ฉันจำได้ว่าการอภิปรายเมื่อหลายปีก่อนในฟอรัม Perl เกี่ยวกับฟังก์ชั่นที่มีชื่อchip()แทนที่จะเป็นchop()(และchimp()เป็นแบบอะนาล็อกchomp())
มาร์คโธมัส

2
str = "[12,23,987,43"

str[0] = ""

7
สิ่งสำคัญคือต้องทราบว่าจะใช้งานได้ใน Ruby 1.9 เท่านั้น ใน Ruby 1.8 สิ่งนี้จะลบไบต์แรกออกจากสตริงไม่ใช่อักขระตัวแรกซึ่งไม่ใช่สิ่งที่ OP ต้องการ
Jörg W Mittag



0

ฉันพบวิธีแก้ปัญหาที่ดีstr.delete(str[0])สำหรับความสามารถในการอ่านแม้ว่าฉันจะไม่สามารถยืนยันถึงประสิทธิภาพได้


0

list = [1,2,3,4] list.drop (1)

# => [2,3,4]

รายการปล่อยองค์ประกอบตั้งแต่หนึ่งรายการขึ้นไปตั้งแต่เริ่มต้นของอาร์เรย์ไม่เปลี่ยนแปลงอาร์เรย์และส่งคืนอาร์เรย์เองแทนที่จะเป็นองค์ประกอบที่ถูกทิ้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.