2012-04-12 14 views
3

Ich sehe immer ersetzen in der Array und Hash-Dokumentation und ich denke immer, dass es seltsam ist.Was sind die Verwendungen von Ruby's Hash.Replace oder Array.Replace?

Ich bin sicher, dass ich so etwas wie dies oft getan haben:

a = [:a, :b, :c, :d] 

... 

if some_condition 
    a = [:e, :f] 
end 

Aber ich hätte nie gedacht, diese stattdessen zu verwenden:

a = [:a, :b, :c, :d] 

... 

if some_condition 
    a.replace [:e, :f] 
end 

Was ich davon ausgehen, ist die beabsichtigte Verwendung. Spart das wirklich Speicher oder hat einen anderen Nutzen, oder ist es nur eine Stilsache?

+0

Ich frage mich, wie oft diese in der freien Natur verwendet werden, z.B. in Schienen. –

Antwort

5

Ich denke, die beabsichtigte Verwendung besteht darin, ein Array vor Ort zu modifizieren, das an eine Methode übergeben wurde. Zum Beispiel:

def m(a) 
    a.replace(%w[a b]) 
end 

a = %w[x y z] 
m(a) 
# a is now ['a', 'b'] 

Ohne replace, würden Sie so etwas zu tun haben:

def m(a) 
    a.clear 
    a << 'a' # or use .push of course 
    a << 'b' 
end 

replace verwenden, können Sie es tun alles auf einmal sollte umgehen die Auto-Schrumpfung und Auto-Anbau (Dies beinhaltet wahrscheinlich das Kopieren von Speicher, was ein Nebeneffekt des Ersatzes des Array-Inhalts (nicht des Arrays selbst!) Element für Element wäre. Der Leistungsvorteil (falls vorhanden) ist wahrscheinlich nur ein Extra, die primäre Absicht besteht wahrscheinlich darin, Zeiger-zu-Zeiger-Verhalten zu erhalten, ohne dass Zeiger eingeführt oder das Feld in ein zusätzliches Objekt gewickelt werden müssen.

1
a = [:a, :b, :c, :d] 
b = [:x, :y, :z] 
a.replace(b) 

a.object_id == b.object_id 
=> false 

a = [:a, :b, :c, :d] 
b = [:x, :y, :z] 
a = b 

a.object_id == b.object_id 
=> true 

Auch

a = [:a, :b, :c, :d] 
c = a 
b = [:x, :y, :z] 
a.replace(b) 
p C# => [:x, :y, :z] 

vs

a = [:a, :b, :c, :d] 
c = a 
b = [:x, :y, :z] 
a = b 
p C# => [:a, :b, :c, :d] 

diese Antwort Ihre Frage nicht genau.

6

a = [: e, f], und a.replace [: e, f],

die beiden Anweisungen erzeugten Anweisungen wie folgt:

1.

a = [:a, :b, :c, :d] 
a = [:e, :f] 

Anleitung:

Rubin --dump = insns test.rb

== disasm: <RubyVM::InstructionSequence:<main>@test.rb>================= 
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) 
[ 2] a 
0000 trace   1            ( 1) 
0002 duparray   [:a, :b, :c, :d] 
0004 setdynamic  a, 0 
0007 trace   1            ( 2) 
0009 duparray   [:e, :f] 
0011 dup 
0012 setdynamic  a, 0 
0015 leave 

2.

a = [:a, :b, :c, :d] 
a.replace([:e, :f]) 

Anweisungen:

Rubin --dump = insns Test. rb

== disasm: <RubyVM::InstructionSequence:<main>@test.rb>================= 
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) 
[ 2] a 
0000 trace   1            ( 1) 
0002 duparray   [:a, :b, :c, :d] 
0004 setdynamic  a, 0 
0007 trace   1            ( 2) 
0009 getdynamic  a, 0 
0012 duparray   [:e, :f] 
0014 send    :replace, 1, nil, 0, <ic:0> 
0020 leave 

Die ersetzen Methode nicht schneller als Zuweisungsoperator ist, aber ersetzen kann Empfängerarray an Ort und Stelle ändern und, ersetzen Methode wirklich Speicher speichern, kann dies aus gesehen werden Die Quelle von rb_ary_replace.

VALUE 
rb_ary_replace(VALUE copy, VALUE orig) 
{ 
rb_ary_modify_check(copy); 
orig = to_ary(orig); 
if (copy == orig) return copy; 

if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) 
{ 
    VALUE *ptr; 
    VALUE shared = 0; 

    if (ARY_OWNS_HEAP_P(copy)) 
    { 
     xfree(RARRAY_PTR(copy)); 
    } 
    else if (ARY_SHARED_P(copy)) 
    { 
     shared = ARY_SHARED(copy); 
     FL_UNSET_SHARED(copy); 
    } 
    FL_SET_EMBED(copy); 
    ptr = RARRAY_PTR(orig); 
    MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig)); 
    if (shared) 
    { 
     rb_ary_decrement_share(shared); 
    } 
    ARY_SET_LEN(copy, RARRAY_LEN(orig)); 
} 
else 
{ 
    VALUE shared = ary_make_shared(orig); 
    if (ARY_OWNS_HEAP_P(copy)) 
    { 
     xfree(RARRAY_PTR(copy)); 
    } 
    else 
    { 
     rb_ary_unshare_safe(copy); 
    } 
    FL_UNSET_EMBED(copy); 
    ARY_SET_PTR(copy, RARRAY_PTR(orig)); 
    ARY_SET_LEN(copy, RARRAY_LEN(orig)); 
    rb_ary_set_shared(copy, shared); 
} 
return copy; } 
+0

+1 für mich über 'ruby - dump = insns 'zu unterrichten –

Verwandte Themen