5

我在Mathematica中定义了一个函数,如果列表中的第 i 个值在 1 中,并且第 i+1 个值为 0,则该函数会切换这两个值。

我将其定义为:

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的 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} 不是符号。>>

您需要的是函数的 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 回答