优雅地改变变量列表:AddTo,TimesBy等的泛化

时间:2011-01-17 08:44:58

标签: language-features wolfram-mathematica

假设我已经定义了一个变量列表

{a,b,c} = {1,2,3}

如果我想将它们加倍,我可以这样做:

{a,b,c} *= 2

变量{a,b,c}现在评估为{2,4,6}。 如果我想对它们应用任意转换函数,我可以这样做:

{a,b,c} = f /@ {a,b,c}

如果不指定两次变量列表,你会怎么做?

(抛开我可能想要一个数组而不是一个明确命名的变量列表的异议。)

2 个答案:

答案 0 :(得分:2)

你可以这样做:

Function[Null, # = f /@ #, HoldAll][{a, b, c}]

例如,

In[1]:= 
{a,b,c}={1,2,3};
Function[Null, #=f/@#,HoldAll][{a,b,c}];
{a,b,c}

Out[3]= {f[1],f[2],f[3]}

或者,您可以在不对f进行硬编码的情况下执行相同操作,但可以定义自定义set函数。如果你给它Listable属性:

,你的foreach循环的效果可以很容易地重现
ClearAll[set];
SetAttributes[set, {HoldFirst, Listable}]
set[var_, f_] := var = f[var];

示例:

In[10]:= {a,b,c}={1,2,3};
set[{a,b,c},f1];
{a,b,c}

Out[12]= {f1[1],f1[2],f1[3]}

您可能还希望在f可列表的情况下获得速度优势,这一点现在特别相关,因为M8 Compile使用户定义的功能在速度方面受益于Listabe,其方式如下:以前只有内置功能才可以。对于set这种情况(当您在速度之后且知道f可列表时),您只需删除set的Listable属性。

答案 1 :(得分:0)

我在解决这个老问题时找到了答案:ForEach loop in Mathematica

定义each函数,如同对该问题的接受答案一样,我们可以用以下方式回答这个问题:

each[i_, {a,b,c}, i = f[i]]