Get a list of all string prefixes

is there a built-in function in the Ruby String class that can give me all the string prefixes in Ruby. Sort of:

 "ruby".all_prefixes => ["ruby", "rub", "ru", "r"] 

Currently, I have made a special function for this:

 def all_prefixes search_string dup_string = search_string.dup return_list = [] while(dup_string.length != 0) return_list << dup_string.dup dup_string.chop! end return_list end 

But I'm looking for something more rubylike, less code and something magical. Note: of course, original_string should remain as it is.

+6
source share
9 answers

Quick test:

 require 'fruity' string = 'ruby' compare do toro2k do string.size.times.collect { |i| string[0..i] } end marek_lipka do (0...(string.length)).map{ |i| string[0..i] } end jorg_w_mittag do string.chars.inject([[], '']) { |(res, memo), c| [res << memo += c, memo] }.first end jorg_w_mittag_2 do acc = '' string.chars.map {|c| acc += c } end stefan do Array.new(string.size) { |i| string[0..i] } end end 

And the winner:

 Running each test 512 times. Test will take about 1 second. jorg_w_mittag_2 is faster than stefan by 19.999999999999996% ± 10.0% stefan is faster than marek_lipka by 10.000000000000009% ± 10.0% marek_lipka is faster than jorg_w_mittag by 10.000000000000009% ± 1.0% jorg_w_mittag is similar to toro2k 
+7
source

No, there is no built-in method for this. You can do it as follows:

 def all_prefixes(string) string.size.times.collect { |i| string[0..i] } end all_prefixes('ruby') # => ["r", "ru", "rub", "ruby"] 
+9
source
 def all_prefixes(str) acc = '' str.chars.map {|c| acc += c } end 
+6
source

What about

 str = "ruby" prefixes = Array.new(str.size) { |i| str[0..i] } #=> ["r", "ru", "rub", "ruby"] 
+5
source

A bit shorter:

 def all_prefixes(search_string) (0...(search_string.length)).map{ |i| search_string[0..i] } end all_prefixes 'ruby' # => ["r", "ru", "rub", "ruby"] 
+4
source

This may be a long snapshot, but if you want to find various abbreviations for a rowset, you can use the Abbrev module:

 require 'abbrev' Abbrev.abbrev(['ruby']).keys => ["rub", "ru", "r", "ruby"] 
+4
source
 def all_prefixes(str) str.chars.inject([[], '']) {|(res, memo), c| [res << memo += c, memo] }.first end 
+1
source
 str = "ruby" prefixes = str.size.times.map { |i| str[0..i] } #=> ["r", "ru", "rub", "ruby"] 
+1
source

Two not mentioned earlier and faster than in @ toro2k accepted the comparison.

 (1..s.size).map { |i| s[0, i] } => ["r", "ru", "rub", "ruby"] Array.new(s.size) { |i| s[0, i+1] } => ["r", "ru", "rub", "ruby"] 

Strange, no one used String#[start, length] before, only slower than String#[range] .
And I think that at least my first decision is pretty simple.

Test results (using Ruby 2.4.2):

  user system total real toro2k 14.594000 0.000000 14.594000 ( 14.724630) marek_lipka 12.485000 0.000000 12.485000 ( 12.635404) jorg_w_mittag 16.968000 0.000000 16.968000 ( 17.080315) jorg_w_mittag_2 11.828000 0.000000 11.828000 ( 11.935078) stefan 10.766000 0.000000 10.766000 ( 10.831517) stefanpochmann 9.734000 0.000000 9.734000 ( 9.765227) stefanpochmann 2 8.219000 0.000000 8.219000 ( 8.240854) 

My control code:

 require 'benchmark' string = 'ruby' @n = 10**7 Benchmark.bm(20) do |x| @x = x def report(name, &block) @x.report(name) { @n.times(&block) } end report('toro2k') { string.size.times.collect { |i| string[0..i] } } report('marek_lipka') { (0...(string.length)).map{ |i| string[0..i] } } report('jorg_w_mittag') { string.chars.inject([[], '']) { |(res, memo), c| [res << memo += c, memo] }.first } report('jorg_w_mittag_2') { acc = '' string.chars.map {|c| acc += c } } report('stefan') { Array.new(string.size) { |i| string[0..i] } } report('stefanpochmann') { (1..string.size).map { |i| string[0, i] } } report('stefanpochmann 2') { Array.new(string.size) { |i| string[0, i+1] } } end 
0
source

Source: https://habr.com/ru/post/951109/


All Articles