Пример:
[12,23,987,43
Какой самый быстрый и эффективный способ удалить "[",
используя, возможно, chop(), но для первого символа?
Пример:
[12,23,987,43
Какой самый быстрый и эффективный способ удалить "[",
используя, возможно, chop(), но для первого символа?
Я предпочитаю использовать что-то вроде:
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 также могут быть ограничены плохо написанным регулярным выражением, которое встречается гораздо медленнее, чем поиск подстроки. Если возможно, привяжите регулярное выражение, чтобы получить максимальную скорость от него. Здесь есть ответы на "Переполнение стека", демонстрирующие, что для поиска требуется поиск, если вам нужна дополнительная информация.
Как и в ответ Пабло выше, но очиститель оттенков:
str[1..-1]
Вернет массив от 1 до последнего символа.
'Hello World'[1..-1]
 => "ello World"
Мы можем использовать срез для этого:
val = "abc"
 => "abc" 
val.slice!(0)
 => "a" 
val
 => "bc" 
Используя slice!, мы можем удалить любой символ, указав его индекс.
Я предпочитаю это:
str = "[12,23,987,43"
puts str[1..-1]
>> 12,23,987,43
Если вы всегда хотите снять ведущие скобки:
"[12,23,987,43".gsub(/^\[/, "")
Если вы просто хотите удалить первый символ, и знаете, что он не будет в многобайтном наборе символов:
"[12,23,987,43"[1..-1]
или
"[12,23,987,43".slice(1..-1)
 Начиная с Ruby 2.5 вы можете использовать delete_prefix или delete_prefix! добиться этого в читабельной форме.
 В этом случае "[12,23,987,43".delete_prefix("[").
Больше информации здесь:
https://blog.jetbrains.com/ruby/2017/10/10-new-features-in-ruby-2-5/
https://bugs.ruby-lang.org/issues/12694
'invisible'.delete_prefix('in') #=> "visible"
'pink'.delete_prefix('in') #=> "pink"
 Обратите внимание, что вы также можете использовать это, чтобы удалить элементы из конца строки с помощью delete_suffix и delete_suffix!
'worked'.delete_suffix('ed') #=> "work"
'medical'.delete_suffix('ed') #=> "medical"
https://bugs.ruby-lang.org/issues/13665
Редактировать:
 Используя настройку Tin Man, он тоже выглядит довольно быстро (под последними двумя записями delete_p и delete_p!). Не совсем уместен предыдущий фаворит по скорости, хотя очень читабелен.
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)
Неэффективная альтернатива:
str.reverse.chop.reverse
Например: 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" 
Таким образом вы можете удалить один за другим первый символ строки.
Простой способ:
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()
(Примечание: предпочитайте простой способ:))
Благодаря @the-tin-man для составления тестов!
Увы, мне не очень нравится какое-либо из этих решений. Либо они требуют дополнительного шага для получения результата ([0] = '', .strip!), либо они не очень семантичны/понятны о том, что происходит ([1..-1]: "Um, диапазон от 1 до отрицательного 1? Yearg?" ), или они медленны или длинны для записи (.gsub, .length).
То, что мы пытаемся, является "сдвигом" (в языке Array), но возвращающим оставшиеся символы, а не тем, что было смещено. Позвольте использовать наш Ruby, чтобы сделать это возможным со строками! Мы можем использовать скоринговую операцию, но дать ей хорошее имя и взять аргумент, чтобы указать, сколько мы хотим отбросить фронт:
class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end
Но мы можем сделать это быстрее, но неудобно. В то время как мы находимся в этом, для полноты, напишем a #shift и #first для String (почему у Array есть все самое интересное?), Взяв arg, чтобы указать, сколько символов мы хотим удалить с самого начала:
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 (что действительно должно быть методом bang?). И мы можем легко получить модифицированную строку, а также с помощью #eat!. Hm, мы должны поделиться нашей новой мощностью 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] 
Это лучше!
str = "[12,23,987,43"
str[0] = ""
class String
  def bye_felicia()
    felicia = self.strip[0] #first char, not first space.
    self.sub(felicia, '')
  end
end
Использование регулярного выражения:
str = 'string'
n = 1  #to remove first n characters
str[/.{#{str.size-n}}\z/] #=> "tring"
 Я считаю хорошим решением быть str.delete(str[0]) для его читабельности, хотя я не могу подтвердить его производительность.
list = [1,2,3,4] list.drop(1)
# => [2,3,4]
List удаляет один или несколько элементов с начала массива, не изменяет массив и возвращает сам массив вместо удаленного элемента.