2011-10-17 19 views
8

是否有人能夠確定哪些算法用於包含? Ruby中的方法?例如Ruby中用於「String#include?」的算法

"helloworld".include?("hello") 
+7

你知道你可以看看[出處](http://apidock.com/ruby/String/include%3F),對不對? (然後查看C源代碼,至少對於字符串的包含。) –

回答

10

由於浮雕狀態,String#include調用rb_str_index。該功能依次調用rb_memsearch,該功能實現Rabin-Karp string search algorithm,根據this postruby-forum.com

+0

+1鏈接到帖子;) – lucapette

+0

'string [substr]'是否爲搜索調用相同的函數?我的意思是*相同的算法,相同的速度*。 – Nakilon

5

這是實際執行的String#include?

static VALUE 
rb_str_include(VALUE str, VALUE arg) 
{ 
    long i; 

    StringValue(arg); 
    i = rb_str_index(str, arg, 0); 

    if (i == -1) return Qfalse; 
    return Qtrue; 
} 

因此實際使用的算法可以在rb_str_index找到。在他的回答

+5

然後使用'rb_memsearch',它實現[Karp Rabin](http://en.wikipedia.org/wiki/Rabin%E2%80% 93Karp_string_search_algorithm)算法(根據[本文](http://www.ruby-forum.com/topic/87830))。 – rdvdijk

+0

@rdvdijk:我會讓這個答案:-) –

+0

@rdvdijk很好的一個。你應該回答這個問題。然後我會刪除我的答案。 – emboss

6

Ruby語言規範沒有規定任何特定的算法。每個實現可以使用他們想要的任何算法。

例如,在RubiniusString#include?呼叫String#find_string

def include?(needle) 
    if needle.kind_of? Fixnum 
    needle = needle % 256 
    str_needle = needle.chr 
    else 
    str_needle = StringValue(needle) 
    end 

    !!find_string(str_needle, 0) 
end 

String#find_string反過來經由string_index原語實現:

def find_string(pattern, start) 
    Rubinius.primitive :string_index 
    raise PrimitiveFailure, "String#find_string failed" 
end 

的​​原語由rubinius::String::index功能實現:

// Rubinius.primitive :string_index 
Fixnum* index(STATE, String* pattern, Fixnum* start); 

rubinius::String::index

Fixnum* String::index(STATE, String* pattern, Fixnum* start) { 
    native_int total = size(); 
    native_int match_size = pattern->size(); 

    if(start->to_native() < 0) { 
    Exception::argument_error(state, "negative start given"); 
    } 

    switch(match_size) { 
    case 0: 
    return start; 
    case 1: 
    { 
     uint8_t* buf = byte_address(); 
     uint8_t matcher = pattern->byte_address()[0]; 

     for(native_int pos = start->to_native(); pos < total; pos++) { 
     if(buf[pos] == matcher) return Fixnum::from(pos); 
     } 
    } 
    return nil<Fixnum>(); 
    default: 
    { 
     uint8_t* buf = byte_address(); 
     uint8_t* matcher = pattern->byte_address(); 

     uint8_t* last = buf + (total - match_size); 
     uint8_t* pos = buf + start->to_native(); 

     while(pos <= last) { 
     // Checking *pos directly then also checking memcmp is an 
     // optimization. It's about 10x faster than just calling memcmp 
     // everytime. 
     if(*pos == *matcher && 
      memcmp(pos, matcher, match_size) == 0) { 
      return Fixnum::from(pos - buf); 
     } 
     pos++; 
     } 
    } 
    return nil<Fixnum>(); 
    } 
} 
+0

+1表示它完全實現特定。 –