Comment puis-je trouver si une chaîne commence par une autre chaîne dans Ruby?

Réponses:

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

[modifier] C'est quelque chose que je ne savais pas avant cette question: start_withprend plusieurs arguments.

'abcdefg'.start_with?( 'xyz', 'opq', 'ab')
Steenslag
la source
1
L'IRM 1.8.7 n'en a pas start_with?, mais l'IRM 1.9 le fait, tout comme Rails.
Wayne Conrad
@Wayne Conrad: Étrangement, 1.8.7 n'avoir la documentation . String#start_with?
Jörg W Mittag
@ Jörg W Mittag, peut-être pas étrangement, j'avais tort. MRI 1.8.7 a en effet start_with?. Je suppose que je l'ai tapé quand j'ai chargé irb pour l'essayer.
Wayne Conrad
7
Il est intéressant de noter que Rails définit la grammaire correcte starts_with?, qui dans 1.8.7 et au-dessus est juste aliasée start_with?.
Mark Thomas
56

Puisqu'il y a plusieurs méthodes présentées ici, je voulais savoir laquelle était la plus rapide. En utilisant 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

Il semble donc que ce soit start_with?le plus rapide du peloton.

Résultats mis à jour avec Ruby 2.2.2p95 et une machine plus récente:

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
la source
4
pas surprenant étant donné que la compilation et les tests d'expressions régulières sont beaucoup plus difficiles que de simplement comparer des octets
akostadinov
1
Il convient de noter que Regex est bien supérieur pour les recherches insensibles à la casse, même si vous avez calculé toutes les permutations d'observations pour la chaîne de test à l'avance.
Peter P.
3
@PeterP. Je viens de tester des recherches insensibles à la casse, et start_with? vient toujours en avance si vous venez downcase la chaîne de recherche puis comparer avec la chaîne de recherche minuscule: "FooBar".downcase.start_with?("foo").
haslo
4

La méthode mentionnée par steenslag est laconique et compte tenu de la portée de la question, elle doit être considérée comme la bonne réponse. Cependant, il est également intéressant de savoir que cela peut être réalisé avec une expression régulière, qui, si vous n'êtes pas déjà familier avec Ruby, est une compétence importante à apprendre.

Jouez avec Rubular: http://rubular.com/

Mais dans ce cas, l'instruction ruby ​​suivante retournera true si la chaîne de gauche commence par «abc». Le \ A dans le littéral regex à droite signifie «le début de la chaîne». Jouez avec rubular - il deviendra clair comment les choses fonctionnent.

'abcdefg' =~  /\Aabc/ 
pakeha
la source
Comme l'a souligné Wayne Conrad, cette méthode fonctionnera également sur une plus grande variété d'exécutions que start_with.
pakeha
2

J'aime

if ('string'[/^str/]) ...
l'homme d'étain
la source
8
Vous devriez utiliser [/\Astr/]ici. Votre regex correspond également "another\nstring".
haslo