2012-10-13 62 views
4

我在Mathematica中定義了一個函數其中,如果列表中的第i個值爲1,並且第i + 1個值爲0,則函數將切換這兩個值。Set :: setps:在零件分配中不是符號。 >>

我把它定義爲:

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

然而,當我與i = 2測試,並x = {1,1,0,0}我收到以下錯誤:

Set::setps: {1,1,0,0} in the part assignment is not a symbol. >>

我不太知道我是什麼做錯了,因爲我認爲我正確地調用了一切。

回答

0

我想通了;我需要不改變x本身的價值。哎呀!

3

您似乎找到了一個解決方案,不過我們先來解決這個問題。

首先你有一個簡單的轉錄錯誤,你的Set s應用原始值而不是交換它們。隨着這一變化的基本代碼工作:

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。爲了使其成爲函數,我們必須將的名稱x轉換爲此代碼而不是的值x。這是你錯誤的根源:

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

Set::setps: {1,1,0,0} in the part assignment is not a symbol. >>

你需要的是你的函數保持屬性:

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數據的副本,我們不需要保持屬性:

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} 

注意內Modulex是一個局部變量,而不是您的全球名單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}