2011-10-17 5 views
8

どのアルゴリズムがインクルードに使用されているのかを特定できますか? Rubyのメソッド?例"String#include?"のRubyで使用されるアルゴリズム

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

あなたは右、[ソース](http://apidock.com/ruby/String/include%3F)で見ることができます知っていますか? (その後、少なくともStringのインクルードのためにCソースを見てください) –

答えて

10

エンボスの状態は、彼の答えでは、String#includerb_str_indexとなります。この関数はthis postruby-forum.comに従ってRabin-Karp string search algorithmを実装するrb_memsearchを呼び出します。

+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

これは、[Karp Rabin](http://en.wikipedia.org/wiki/Rabin%E2%80%)を実装する 'rb_memsearch'を使います93Karp_string_search_algorithm)アルゴリズム([this post](http://www.ruby-forum.com/topic/87830)による)。 – rdvdijk

+0

@rdvdijk:私はこれを答えにします:-) –

+0

@rdvdijkいいです。あなたはこれに答えるべきです。私はそれから私の答えを削除します。 – emboss

6

Ruby言語仕様は、特定のアルゴリズムを規定していません。すべての実装で、必要なアルゴリズムを使用できます。 Rubinius、例えば

String#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_stringstring_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は実装固有のものです。 –

関連する問題