2013-08-06 31 views
6

là có bất kỳ chức năng sẵn có nào trong lớp Ruby String có thể cho tôi tất cả các tiền tố của một chuỗi trong Ruby. Một cái gì đó như:Nhận danh sách tất cả các tiền tố của một chuỗi

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

Hiện nay tôi đã thực hiện một chức năng tùy chỉnh cho việc này:

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 

Nhưng tôi đang tìm kiếm một cái gì đó hơn rubylike, ít mã và một cái gì đó huyền diệu. Lưu ý: tất nhiên là không cần phải nói rằng original_string sẽ vẫn như cũ.

+1

Tôi nghĩ rằng những gì bạn có là tốt, đủ đủ, vì đó trông điều rất hiếm khi được sử dụng. – Smar

+2

Đây có thể là một cảnh quay dài, nhưng nếu bạn muốn tìm các chữ viết tắt khác nhau cho một tập hợp các chuỗi, bạn có thể sử dụng 'Abbrev': http://www.ruby-doc.org/stdlib-2.0/libdoc/abbrev/rdoc /Abbrev.html – nTraum

+1

@nTraum: Bạn có thể thay đổi nhận xét đó thành câu trả lời được không?/tôi là ngứa để cung cấp cho bạn một upvote :) – creinig

Trả lời

7

Một điểm chuẩn nhanh:

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 

Và người chiến thắng là:

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 
+0

không ai có thể phủ nhận rằng điều này xứng đáng là câu trả lời hay nhất :) –

+1

Tôi sẽ từ chối nó! Điểm chuẩn cho điều gì đó tầm thường vì điều này không phải là yếu tố quyết định giải pháp nào là tốt nhất, trừ khi bạn đang đẩy giới hạn về độ dài đầu vào, vv Sự khác biệt trong thế giới thực sẽ không quan trọng nhiều như khả năng đọc. Thật trùng hợp tôi đã tìm thấy câu trả lời khác của @ toro2k là sở thích của tôi. –

4

Một chút hình thức ngắn hơn:

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

cảm ơn, mặc dù câu trả lời của bạn giống như toro2k, nhưng câu trả lời đó trông sạch hơn một chút. –

+0

Thực ra mã của bạn trả về '[" r "," ru "," chà "," ruby ​​"," ruby ​​"]', bạn nên sử dụng một phạm vi độc quyền, tức là '0 ... string.size' thay vì' 0 ..string.size'. Và 'string [..]' phải là 'search_string [...]'. – toro2k

+0

@ toro2k cảm ơn. Nó thực sự là một lỗi đánh máy. –

9

Không, không có built-in phương pháp cho việc này. Bạn có thể làm điều đó như thế này:

def all_prefixes(string) 
    string.size.times.collect { |i| string[0..i] } 
end 
all_prefixes('ruby') 
# => ["r", "ru", "rub", "ruby"] 
+0

cảm ơn .. điều này có vẻ sạch hơn với tôi. –

1
def all_prefixes(str) 
    str.chars.inject([[], '']) {|(res, memo), c| [res << memo += c, memo] }.first 
end 
5

gì về

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

điều này thực sự là sạch nhất của tất cả (imho). –

6
def all_prefixes(str) 
    acc = '' 
    str.chars.map {|c| acc += c } 
end 
+0

nhanh nhất trong số các giải pháp được trình bày tại đây. –

1
str = "ruby"  
prefixes = str.size.times.map { |i| str[0..i] } #=> ["r", "ru", "rub", "ruby"] 
4

Đây là có thể là một shot dài, nhưng nếu bạn muốn tìm từ viết tắt riêng biệt cho một tập hợp các chuỗi, bạn có thể sử dụng Abbrev mô-đun:

require 'abbrev' 

Abbrev.abbrev(['ruby']).keys 
=> ["rub", "ru", "r", "ruby"] 
+0

điều này sẽ là câu trả lời hay nhất nếu tôi có thể thực hiện 'Abbrev.abbrev ('ruby'). Keys' thay vì' Abbrev.abbrev (['ruby']). Keys', nhưng bài báo này khá hay –

0

Hai không được đề cập trước và nhanh hơn so với những người trong so sánh được chấp nhận của @ toro2k answer.

(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"] 

Kỳ lạ thay, không ai sử dụng String#[start, length] trước, chỉ chậm hơn String#[range].
Và tôi nghĩ ít nhất giải pháp đầu tiên của tôi khá đơn giản.

kết quả Benchmark (sử dụng của 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) 

đang benchmark của tôi:

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 
Các vấn đề liên quan