문자열에서 첫 번째 문자를 제거하는 가장 쉬운 방법은 무엇입니까?


174

예:

[12,23,987,43

첫 번째 문자를 [사용하여 " " 를 제거하는 가장 빠르고 효율적인 방법은 무엇입니까 chop()?


1
답변을 수정 했으므로 선택한 답변을 변경할 수 있습니다. Jason Stirk의 답변이 가장 빠르며 읽기 쉬우므로 답변을 수여하십시오.
Tin Man

3
아래 답변에 따라 가장 빠른 str [1 ..- 1]을 사용하십시오.
Achyut Rastogi

1
루비 2.5로서 당신은 사용할 수 있습니다 delete_prefixdelete_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또한 하위 문자열 검색보다 훨씬 더 느리게 일치 잘못 작성된 정규식에 의해 장애인 수 있습니다. 가능한 경우 정규 표현식을 고정하여 가장 빠른 속도를 얻으십시오. 여기에 스택 오버플로에 대한 답변이 있으므로 추가 정보를 원하면 검색하십시오.


34
이것은 Ruby 1.9에서만 작동한다는 점에 유의해야합니다. 루비 1.8,이 첫 번째 제거 바이트를 문자열에서 하지 영업 이익이 원하는 것을하지 않은 첫 번째 문자.
Jörg W Mittag

+1 : 문자열 위치에 단일 문자뿐만 아니라 하위 문자열을 삽입 할 수 있다는 것을 항상 잊습니다. 감사!
quetzalcoatl

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

4
이것은 모든 위치에서 그것을 삭제합니다. OP가 원했던 것이 아닙니다 : "... 첫 번째 문자?"
Tin Man

2
" what about "[12,23,987,43".shift ?"? "[12,23,987,43".shift NoMethodError: undefined method "[12,23,987,43": String` 에 대한 shift '는 어떻습니까?
Tin Man

293

위의 Pablo의 대답과 비슷하지만 그늘 청소기 :

str[1..-1]

배열을 1에서 마지막 문자로 반환합니다.

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

13
+1 내 답변에 추가 한 벤치 마크 결과를 살펴보십시오. 가장 빠른 런타임을 얻었으며 매우 깨끗하다고 ​​생각합니다.
Tin Man

str[1,]위와 비교 하여 성능은 어떻습니까?
Bohr

1
@Bohr : str[1,]범위가이므로 두 번째 문자를 반환합니다 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를 사용하고 곡사포로 비행하는 것처럼) 이 우아한 것은 실제로 선택된 대답이어야합니다 .
f055

1
표면적으로 직관적이지 않은 것처럼 보일 수 있지만 추가 작업 []=slice!필요한 기본 C 코드를 많이 필요로하지 않습니다 . 추가됩니다. 논쟁은 "어느 것이 더 읽기 쉬운가?" 나는 []=읽을 수있는 것을 사용 하지만 C-> Perl 배경에서 왔을 것입니다. 자바 개발자들은 아마도 읽기가 어렵다고 생각할 것입니다. 쉽게 이해하고 유지 관리 할 수 ​​있고 CPU를 부적절하게로드하지 않는 한 작업을 수행 할 수있는 적절한 방법입니다.
Tin Man

확인. 함수가 ROR에서 많은 CPU로드를 사용하는지 측정 할 수있는 방법을 알고 있습니까? 또는 밀리 초 또는 나노초 단위의 실행 시간 차이를 사용해야합니까?
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_suffixdelete_suffix!

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

편집하다:

Tin Man의 벤치 마크 설정을 사용하면 (마지막 두 항목 아래 delete_pdelete_p!) 매우 빠릅니다 . 하지 않습니다 매우 하지만, 속도에 대한 이전의 제품 구입에 PIP 매우 읽을 수 있습니다.

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(/^\[/, ""). 첫 번째는 정규식 엔진이 모든 일치 항목을 찾은 다음 한 번의 작업으로 교체되어 Ruby 1.9.3과 비교하여 속도가 약 2 배 향상됩니다.
Tin Man

1
우리는 문자열을 다루고 있기 때문에 이것이되어야 gsub(/\A\[/, "") 합니까?
Sagar Pandya

6

비효율적 인 대안 :

str.reverse.chop.reverse

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의 답변 과 동일 합니다.
Tin Man

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
"chop"의미를 유지하려면 다음과 같이하십시오."[12,23,987,43".reverse.chop.reverse
Chris Heald

그것은 꽤 큰 성능 오버 헤드를 하나 개의 문자 제거하는 것입니다
파블로 페르난데스

7
왜 [1..self.length] 대신 [1 ..- 1]을 사용하지 않습니까?
horseyguy

원숭이 패치 예제는이 질문에 꽤 적합합니다. 그것은 관련이없고 추악한 IMO입니다.
dredozubov 2014 년

3

벤치 마크를 구성한 @ the-tin-man에게 감사합니다!

아아, 나는 그 해결책을 정말로 좋아하지 않는다. 결과를 얻는 데 추가 단계가 필요 하거나 ( [0] = '', .strip!) 또는 무슨 일이 일어나고 있는지에 대한 의미가 명확하지 않거나 ( [1..-1]"음, 1에서 음수 1? Yearg?") 느리거나 길다 ( .gsub, .length)를 쓰십시오 .

우리가 시도하는 것은 'shift'(배열 어휘)이지만 전환 된 것이 아니라 나머지 문자를 반환합니다. 우리의 루비를 사용하여 이것을 문자열로 가능하게합시다! 빠른 괄호 연산을 사용할 수 있지만 좋은 이름을 지정하고 앞면에서 얼마나 많은 부분을 쪼개고 싶은지를 지정합니다.

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

그러나 신속하지만 다루기 힘든 브래킷 조작으로 더 많은 일을 할 수 있습니다. 우리가 그것을 완성하는 동안 완전성을 위해 #shiftand를 #first위해 (어레이는 왜 모든 재미를 가져야 하는가?), 우리가 처음부터 제거 할 문자 수를 지정하기 위해 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#firstArray#shift(이 정말 ?? 쾅 방법이어야한다)를. 그리고 우리는 쉽게 수정 된 문자열을 얻을 수 있습니다 #eat!. 흠, 우리는 새로운 eat!ing 힘을 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
나는의 이름으로 이러한 기능에 대해 펄 포럼에서 토론 년 전 기억 chip()대신에 chop()(와 chimp()의 아날로그 등 chomp())을.
Mark Thomas

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

str[0] = ""

7
이것은 Ruby 1.9에서만 작동한다는 점에 유의해야합니다. 루비 1.8,이 첫 번째 제거 바이트를 문자열에서 하지 영업 이익이 원하는 것을하지 않은 첫 번째 문자.
Jörg W Mittag

0
class String
  def bye_felicia()
    felicia = self.strip[0] #first char, not first space.
    self.sub(felicia, '')
  end
end

0

정규식 사용 :

str = 'string'
n = 1  #to remove first n characters

str[/.{#{str.size-n}}\z/] #=> "tring"

0

str.delete(str[0])가독성에 대한 좋은 해결책을 찾았 지만 성능을 증명할 수는 없습니다.


0

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

# => [2,3,4]

List는 배열의 시작 부분에서 하나 이상의 요소를 삭제하고 배열을 변경하지 않고 삭제 된 요소 대신 배열 자체를 반환합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.