2017-09-03 23 views
2

私は[3、1、2、0]、私は( "ABCD" をscramble_string実行する場合origStringと呼ばれるこの変数は、例えば、私のループ変数変化値、ルビー

def scramble_string(string, positions) 
    i = 0 
    origString = string 
    puts origString 
    newString = string 
    while i < string.length 
    newString[i] = origString[positions[i]] 
    i = i + 1 
    end 
    puts origString 
    return newString 
end 

の値を変更する方法を確認していません) origStringは、最初の "puts"の "abcd"から2番目の "puts"に変更されます。 origStringの値を1回だけ宣言する場合、どのように値を変更しますか?

+1

Rubyでは大文字と小文字が区別されるため、 'orig_string'のような名前を使用することを強くお勧めします。 – tadman

+0

変数は値を変更していません。あなたはそれを7行目に伝えているので、値はその内容を変更しています。 –

+0

@JörgWMittagあなたは精巧にできますか?それはどのように機能して "価値はその内容を変化させている"。 – Aparichith

答えて

4

ルビーでx = yと言うとき、まったく同じオブジェクトへの参照を持つ変数が作成されます。 xに対する変更はyとその逆に適用されます:

y = "test" 
x = y 

x[0] = "b" 

x 
# => "best" 
y 
# => "best" 

あなたはこのために伝えることができます:彼らは同じオブジェクトだ

x.object_id == y.object_id 
# => true 

。何が欲しいのは最初のコピーを作成することです。

x = y.dup 
x[0] = "b" 
x 
# => "best" 
y 
# => "test" 

これは、2つの独立したオブジェクトになり:

orig_string = string.dup 

x.object_id == y.object_id 
# => false 

は、だからあなたの場合には何が必要かのようにそれを変更することです

Rubyで処理する最良の方法は、コピーを返す関数を使用することです。より良い解決策は次のとおりです。

def scramble_string(string, positions) 
    (0...string.length).map do |p| 
    string[positions[p]] 
    end.join 
end 

scramble_string("abcd", [3, 1, 2, 0]) 
"dbca" 

文字列操作のバージョンよりもはるかに簡潔です。

+0

'string.chars.values_at(* positions).join' – Stefan

+0

@tadmanはあなたのステートメントについていくつかの説明が必要です。 'x = y'と言うとき、両方のobject_idsは同じですが、x [0]とy [0]のobject_idsは異なります。 'x = 'pest''の値全体を変更すると、object_idは完全に変更されます。しかし、 'x'の単一の値を変更することは元の文字列' y'に反映されますか? これについてもう少し詳しく知る必要があります。 – Aparichith

+0

'x [0]'は1文字の部分文字列を返します。すべての部分文字列演算は*新しい一意の文字列*を生成できるので、 'x [0] .object_id == x [0] .object_id'でも一般的に真ではありません。設計上、object_idに相当するものは、Symbols、nil、true、false、および* some *の数だけです。 – tadman