Jak mogę sprawdzić, czy ciąg znaków zaczyna się od innego ciągu w Rubim?

Odpowiedzi:

254
puts 'abcdefg'.start_with?('abc')  #=> true

[edytuj] To jest coś, czego nie wiedziałem przed tym pytaniem: start_withprzyjmuje wiele argumentów.

'abcdefg'.start_with?( 'xyz', 'opq', 'ab')
steenslag
źródło
1
MRI 1.8.7 nie ma start_with?, ale MRI 1.9 tak, jak robi to Rails.
Wayne Conrad,
@Wayne Conrad: dziwne, 1.8.7 nie posiadają dokumentacji String#start_with?.
Jörg W Mittag
@ Jörg W Mittag, może nie dziwnie, myliłem się. MRI 1.8.7 rzeczywiście ma start_with?. Wydaje mi się, że pomyliłem się, kiedy załadowałem irb, aby spróbować.
Wayne Conrad
7
Co ciekawe, Railsy definiują poprawność gramatyczną starts_with?, która w wersji 1.8.7 i nowszych jest aliasowana do start_with?.
Mark Thomas
56

Ponieważ zaprezentowano tutaj kilka metod, chciałem dowiedzieć się, która z nich jest najszybsza. Używając Ruby 1.9.3p362:

irb(main):001:0> require 'benchmark'
=> true
irb(main):002:0> Benchmark.realtime { 1.upto(10000000) { "foobar"[/\Afoo/] }}
=> 12.477248
irb(main):003:0> Benchmark.realtime { 1.upto(10000000) { "foobar" =~ /\Afoo/ }}
=> 9.593959
irb(main):004:0> Benchmark.realtime { 1.upto(10000000) { "foobar"["foo"] }}
=> 9.086909
irb(main):005:0> Benchmark.realtime { 1.upto(10000000) { "foobar".start_with?("foo") }}
=> 6.973697

Wygląda na to, że start_with?jest najszybszy z całej paczki.

Zaktualizowane wyniki dla Rubiego 2.2.2p95 i nowszej maszyny:

require 'benchmark'
Benchmark.bm do |x|
  x.report('regex[]')    { 10000000.times { "foobar"[/\Afoo/] }}
  x.report('regex')      { 10000000.times { "foobar" =~ /\Afoo/ }}
  x.report('[]')         { 10000000.times { "foobar"["foo"] }}
  x.report('start_with') { 10000000.times { "foobar".start_with?("foo") }}
end

            user       system     total       real
regex[]     4.020000   0.000000   4.020000 (  4.024469)
regex       3.160000   0.000000   3.160000 (  3.159543)
[]          2.930000   0.000000   2.930000 (  2.931889)
start_with  2.010000   0.000000   2.010000 (  2.008162)
haslo
źródło
4
nic dziwnego, biorąc pod uwagę, że kompilacja i testowanie wyrażeń regularnych jest znacznie trudniejsze niż zwykłe porównywanie bajtów
akostadinov
1
Należy zauważyć, że Regex jest znacznie lepszy w przypadku wyszukiwania bez rozróżniania wielkości liter, nawet jeśli z wyprzedzeniem obliczyłeś wszystkie permutacje obserwacji dla ciągu testowego.
Piotr P.
3
@PeterP. Właśnie przetestowałem wyszukiwania bez rozróżniania wielkości liter i rozpocząć_z? ciągle wychodzi do przodu, jeśli tylko downcase ciąg do wyszukiwania, a następnie porównać z poszukiwaniem ciąg małych liter: "FooBar".downcase.start_with?("foo").
haslo
4

Metoda, o której mówi steenslag, jest zwięzła i biorąc pod uwagę zakres pytania, należy ją uznać za poprawną odpowiedź. Jednak warto również wiedzieć, że można to osiągnąć za pomocą wyrażenia regularnego, którego, jeśli nie znasz jeszcze języka Ruby, jest ważną umiejętnością do nauczenia się.

Zagraj w Rubular: http://rubular.com/

Ale w tym przypadku następująca instrukcja ruby ​​zwróci prawdę, jeśli ciąg po lewej stronie zaczyna się od „abc”. \ A w dosłownym wyrażeniu regularnym po prawej stronie oznacza „początek łańcucha”. Pobaw się rubularem - stanie się jasne, jak to działa.

'abcdefg' =~  /\Aabc/ 
pakeha
źródło
Jak zauważył Wayne Conrad, ta metoda będzie również działać na szerszej gamie środowisk wykonawczych niż start_with will.
pakeha
2

podoba mi się

if ('string'[/^str/]) ...
Blaszany Człowiek
źródło
8
Powinieneś używać [/\Astr/]tutaj. Twoje wyrażenie regularne również pasuje "another\nstring".
haslo