Wolfram mathematica 如何在将函数映射到列表时删除额外的{}
简单的问题,给出这样一个列表Wolfram mathematica 如何在将函数映射到列表时删除额外的{},wolfram-mathematica,Wolfram Mathematica,简单的问题,给出这样一个列表 Clear[a, b, c, d, e, f]; lst = {{a, b}, {c, d}, {e, f}}; 假设我有一个定义如下的函数: foo[x_,y_]:=Module[{},...] 我想把这个函数应用到列表中,所以如果我输入 Map[foo, lst] 这给 {foo[{a, b}], foo[{c, d}], foo[{e, f}]} 我希望它能以 {foo[a, b], foo[c, d], foo[e, f]} 所以它起作用了 最好的
Clear[a, b, c, d, e, f];
lst = {{a, b}, {c, d}, {e, f}};
假设我有一个定义如下的函数:
foo[x_,y_]:=Module[{},...]
我想把这个函数应用到列表中,所以如果我输入
Map[foo, lst]
这给
{foo[{a, b}], foo[{c, d}], foo[{e, f}]}
我希望它能以
{foo[a, b], foo[c, d], foo[e, f]}
所以它起作用了
最好的方法是什么?假设我不能修改函数foo[]定义(假设它是内置的)
我现在知道的只有两种方法是
Map[foo[#[[1]], #[[2]]] &, lst]
{foo[a, b], foo[c, d], foo[e, f]}
(工作太多),或
(输入较少,但需要先转置)
问:还有其他更好的方法来实现上述目标吗?我查看了其他Map及其朋友,我看不到比我拥有的更直接的功能。您需要
在级别应用
或其缩写形式@@
foo@@@lst
{foo[a, b], foo[c, d], foo[e, f]}
一种可能的方法是将lst
的每个元素的头部从List
更改为foo
:
foo @@ # & /@ lst
{foo[a, b], foo[c, d], foo[e, f]}
Apply[foo, lst, {1}]
还有一些可能性可供选择:
这是尤达回答的更详细版本。它仅在列表的第1级应用foo
(用头foo
替换头list
):
这与此相同,但映射应用于列表lst
(基本上是Andrei的答案):
这只是在第1级用foo[x]替换了模式列表[x__;uu]:
Replace[lst, List[x__] -> foo[x], 1]
仅报告这两种方法的令人费解的性能测试(@@@
,@#&/
):
这些结果不是随机的,但对于非常不同的数据大小,它们大致成比例
@@
对于减法
,除法
,幂
,日志
来说大约快3-4倍,而@@@和/
对于加号
和倍
来说大约快4倍,这会引发另一个问题,这(正如人们可以相信的那样)可能稍微
通过以下评估进行澄清:
Attributes@{Plus, Subtract, Times, Divide, Power, Log}
只有Plus
和Times
具有属性Flat
和Orderless
,而在其余的属性中,只有Power
(似乎效率最高)也具有属性OneIdentity
编辑
对观察到的性能提升的可靠解释(感谢Leonid Shifrin的评论)应该走另一条路
默认情况下有mapcilelength->100
,因为我们可以检查SystemOptions[“CompileOptions”]
。
要重置地图的自动编译,我们可以计算:
SetSystemOptions["CompileOptions" -> "MapCompileLength" -> Infinity]
现在,我们可以通过在相关符号和列表上再次评估我们的H
-性能测试函数来测试这两种方法的相对性能:
Table[{ToString[F], H[F, T]}, {F, {Plus, Subtract, Times, Divide, Power, Log}}]
Out[15]= {{"Plus", 0.2898246},
{"Subtract", 0.2979452},
{"Times", 0.2721893},
{"Divide", 0.3078512},
{"Power", 0.3321622},
{"Log", 0.3258972}}
有了这些结果,我们可以得出结论,一般来说,尤达的方法(@@@
)是最有效的,而安德烈提供的方法在加上和时间的情况下效果更好,因为映射的自动编译允许(@&
)有更好的性能 关于Apply[]
的答案非常准确,而且是正确的做法,但您试图做的是将List[]
标题替换为Sequence[]
标题,即List[List[3,5],List[6,7]
应该变成List[Sequence[3,5],Sequence[6,7]
如果删除任何参数列表的头,自然会保留序列头,因此Delete[Plus[3,5],0]
和Delete[{3,5},0]
和Delete[list[3,5],0]
都会产生序列[3,5]
所以foo@Delete[#,0]&/{a,b},{c,d},{e,f}
将为您提供与foo@@@a,b},{c,d},{e,f}
相同的信息
或者,foo[#/.List->Sequence]&/{a,b},{c,d},{e,f}
做同样的事情。问题:将List应用于数学中的参数我不得不不同意他想把List[List[…]转换成List[Sequence[…]
的说法。更准确地说,他想要List[f[…]…]
,即他想要将内部列表的头更改为f
。我同意这是他最终“想要的”。我的意思是在某种意义上说“你想要做的是……”;-)很抱歉给你带来了困惑。要进入列表[f[序列[…],…]
他需要一种方法将列表列表转换为序列列表。Apply是在内部完成的。如果我们记得Map
会在可能的时候自动编译,Apply
只需要三个头就可以编译:加上,倍
和列表
。哦,@@
不自动编译。由于@#&/
结构中的自动编译,并且由于您的输入是一个大的压缩数组(它允许一个人从自动编译中受益),您可以看到Plus
和时间的效率提高。请参见我的回答:,以及下面的注释,有关类似问题的更多讨论。@Leonid感谢您提供有趣的链接和评论。事实上,当我在T1=FromPackedArray[T]
上计算H
函数时,Plus和时间的相对效率大约降低了因子2,而其他函数只降低了几个百分点,但是Map
对于Plus
和times
来说仍然快了近两倍。这种效应的原因显然是自编译。另一方面,关于相关函数属性的评论仍然有效,我希望不要有任何误解。坦率地说,我认为性能差异的唯一原因是自编译,而您提到的其他属性在这种特殊情况下不会造成这种差异。要了解这一点,请执行SetSystemOptions[“CompileOptions”->“MapCompileLength”->Infinity]
——这实际上禁用了自动编译。然后重做计时,您将看到时间
和加上
现在的行为与re相同
Attributes@{Plus, Subtract, Times, Divide, Power, Log}
SetSystemOptions["CompileOptions" -> "MapCompileLength" -> Infinity]
Table[{ToString[F], H[F, T]}, {F, {Plus, Subtract, Times, Divide, Power, Log}}]
Out[15]= {{"Plus", 0.2898246},
{"Subtract", 0.2979452},
{"Times", 0.2721893},
{"Divide", 0.3078512},
{"Power", 0.3321622},
{"Log", 0.3258972}}