5

Mathematicaで関数を定義しています。リストの i 番目の値が 1 で、i+1 番目の値が 0 の場合、関数はこれら 2 つの値を切り替えます。

私はそれを次のように定義しました:

f[i_, x_] := (If[x[[i]] == 1 && x[[i + 1]] == 0, x[[i]] = 1; x[[i + 1]] = 0]);

ただし、テストするとi = 2x = {1,1,0,0}次のエラーが表示されます。

パーツ割り当ての Set::setps: {1,1,0,0} はシンボルではありません。>>

すべてを正しく呼び出していると思っていたので、何が間違っているのかよくわかりません。

4

2 に答える 2

4

解決策を見つけたようですが、とにかくこれを分解しましょう。

Setまず、元の値を交換するのではなく、元の値を適用する単純な転記エラーがあります。この変更により、基本的なコードが機能します。

i = 2;
x = {1, 1, 0, 0};

If[
 x[[i]] == 1 && x[[i + 1]] == 0,
 x[[i]] = 0; x[[i + 1]] = 1;
]

x
{1, 0, 1, 0}

これで、正常に変更されましxた。これを関数にするには、 のではなくの名前をこのコードに渡す必要があります。これがエラーの原因です:xx

{1, 1, 0, 0}[[2]] = 0;

パーツ割り当ての Set::setps: {1,1,0,0} はシンボルではありません。>>

必要なのは、関数の Hold 属性です。

SetAttributes[f, HoldAll]

f[i_, x_] := If[x[[i]] == 1 && x[[i + 1]] == 0, x[[i]] = 0; x[[i + 1]] = 1;]

i = 2 ;
x = {1, 1, 0, 0};

f[2, x]

x
{1, 0, 1, 0}

おそらく、それ自体の値を変更するつもりはなかったかもしれませんxが、この手法は他のアプリケーションで確実に役立ちます。上記の関数を変更してデータのコピーModuleを操作するには、使用する可能性があり、Hold 属性は必要ありません。

f2[i_, xImmutable_] :=
  Module[{x = xImmutable},
    If[x[[i]] == 1 && x[[i + 1]] == 0, x[[i]] = 0; x[[i + 1]] = 1];
    x
  ]

i = 2 ;
x = {1, 1, 0, 0};

f2[2, x]
{1, 0, 1, 0}

xwithinModuleはローカル変数であり、変更されていないグローバル listではないことに注意してくださいx

楽しみのために、これを別の方法で実装してみましょう。

f3[i_, x_] := 
 If[
   x[[i + {0, 1}]] == {1, 0},
   ReplacePart[x, {i -> 0, i + 1 -> 1}],
   x
 ]

f3[2, x]
{1, 0, 1, 0}
于 2012-10-14T05:20:40.553 に答える
1

私はそれを考え出した; x 自体の値を変更する必要はありませんでした。おっと!

于 2012-10-13T19:22:07.127 に答える