如何将值设置为符号

时间:2011-04-18 19:55:06

标签: wolfram-mathematica symbols

我想将值设置为变量列表,如下所示:

list[[1]] = 2

如果list[[1]]a,那么a现在将等于2。我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:9)

好吧,让我们天真地尝试一下:

列出清单:

In[1]:= ClearAll[list, a, b, c]; 
list = {a, b, c}; 

正如我们所期望的那样:

In[3]:= list
Out[3]= {a, b, c}

将第一个元素设置为2:

In[4]:= list[[1]] = 2
Out[4]= 2

In[5]:= list
Out[5]= {2, b, c}

这不会影响:

In[6]:= a 
Out[6]= a

重新开始:

In[7]:= ClearAll[list, a, b, c]; 
list = {a, b, c}; 

In[9]:= list
Out[9]= {a, b, c}

问题是Set(=)有HoldFirst作为其属性之一,即它不评估它的第一个参数是左侧,并且赋值是列表而不是位于该位置的变量。但您可以使用Evaluate强制进行评估:

In[10]:= Evaluate[list[[1]]] = 2
Out[10]= 2

现在列表似乎和以前一样:

In[11]:= list
Out[11]= {2, b, c}

但这只是因为a仍然存在并且值为2(在之前的版本中,a 替换为2):

In[12]:= a
Out[12]= 2

如果您现在将a设置为3,您也会看到更改列表:

In[13]:= a = 3
Out[13]= 3

In[14]:= list
Out[14]= {3, b, c}

编辑

或许更接近问题的措辞,您可以在列表中Map Set

In[16]:= ClearAll[list, a, b, c]; 
list = {a, b, c}; 

In[18]:= Set[#, RandomInteger[10]] & /@ list
Out[18]= {4, 8, 1}

In[19]:= list    
Out[19]= {4, 8, 1}

In[21]:= {a, b, c}    
Out[21]= {4, 8, 1}

答案 1 :(得分:9)

您在Mathematica中要求的内容通常很难,因为很难模仿指针语义。以下代码将专门针对您的要求,但仅限于符号作为列表元素:

ClearAll[setPart];
SetAttributes[setPart, HoldFirst];
setPart[lst_Symbol, i_, value_] :=
  With[{heldPart =  First@Extract[Hold[lst] /. OwnValues[lst], {{1, i}}, Hold]},
    If[MatchQ[heldPart, Hold[_Symbol]],
      Set @@ Append[heldPart, value],
      lst[[i]] = value]];

示例:

In[117]:= Clear[list, a, b]
list = {a, b, c, 4, 5};
a = 1;
b = 3;
list

Out[121]= {1, 3, c, 4, 5}

In[122]:= setPart[list, 1, 10];
{a, list}

Out[123]= {10, {10, 3, c, 4, 5}}

In[124]:= setPart[list, 5, 10];
list

Out[125]= {10, 3, c, 4, 10}

答案 2 :(得分:2)

你也许可以这样做:

setSymbol[symbol_, value_] := Module[{},
    ToExpression[
        SymbolName[symbol] <> "=" <> ToString[value,TotalWidth->Infinity]
    ]
]
setSymbol[list[[1]], 2]

虽然这可能有点hackish。正确的方法是通过讨论如何评估值来进行评估,但我不记得如何;见其他答案。

答案 3 :(得分:2)

当你第一次不知道要重新定义的符号时,我在定义符号的值时遇到了类似的问题。你的回答帮助我找到了正确的方法:

HoldPattern 在这里非常适合我,即使已经为变量设置了值。

In[253]:= Clear[a,b,c,d,list]
list = HoldPattern/@{a,b,c,d};
a=2;
Evaluate[list[[1]]]=1;
list//ReleaseHold
a

Out[257]= {1,b,c,d}
Out[258]= 1

所以我的解决方案非常类似于Sjoerd C. de Vries的第一个解决方案,但它保护符号不被HoldPattern在列表内部进行评估。

请注意,必须使用 ReleaseHold 才能使用该列表进行进一步计算。变量(a,b,c,d)不会受到这种结构的影响。

这是我在这里的第一篇文章,希望你喜欢它; - )