3

Slicing a String "Hello world!"[0, 5] == 'Hello' is a common idiom in Ruby to compare the first or last n characters of a string to another string. Regular expressions can do it too. And then there's start_with? and end_with? which can also do this.

Which should I use for the most speed?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303

1 Answers1

4

Consider these tests:

require 'fruity'

STR = '!' + ('a'..'z').to_a.join # => "!abcdefghijklmnopqrstuvwxyz"

Results for a single character starting a string:

compare do
  _slice { STR[0] == '!' }
  _start_with { STR.start_with?('!') }
  _regex { !!STR[/^!/] }
end

# >> Running each test 32768 times. Test will take about 1 second.
# >> _start_with is faster than _slice by 2x ± 1.0
# >> _slice is similar to _regex

Results for multiple characters starting a string:

compare do
  _slice { STR[0..4] == '!abcd' }
  _start_with { STR.start_with?('!abcd') }
  _regex { !!STR[/^!abcd/] }
end

# >> Running each test 32768 times. Test will take about 2 seconds.
# >> _start_with is faster than _slice by 2x ± 1.0
# >> _slice is similar to _regex

Results for a single character ending a string:

compare do
  _slice { STR[-1] == 'z' }
  _end_with { STR.end_with?('z') }
  _regex { !!STR[/z$/] }
end

# >> Running each test 32768 times. Test will take about 2 seconds.
# >> _end_with is faster than _slice by 2x ± 1.0
# >> _slice is faster than _regex by 2x ± 1.0

Results for multiple characters ending a string:

compare do
  _slice { STR[-5..-1] == 'vwxyz' }
  _end_with { STR.end_with?('vwxyz') }
  _regex { !!STR[/vwxyz$/] }
end

# >> Running each test 16384 times. Test will take about 1 second.
# >> _end_with is faster than _slice by 2x ± 1.0
# >> _slice is similar to _regex

So, for clarity and speed start_with? and end_with? should be our first choices. If we need to use a pattern then slicing or using a regex are the obvious choices.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • benchmarking this makes sense. was expecting start_with? and end_with? to be faster as they probably don't build any string and return it to you and can do the comparison on the string itself. – Mircea Oct 06 '15 at 18:13
  • The reason `start_with?` and `end_with?` are fast is because they're compiled and are using `memcmp()`, not interpreted and don't rely on calling the regex engine. In other words, they rely on C functions meant for comparing characters/bytes, which are blinding fast. – the Tin Man Oct 06 '15 at 18:16
  • i believe we agree :) (i.e. saying the same thing) – Mircea Oct 06 '15 at 18:23