Nas*_*ser 7 wolfram-mathematica
简单的问题,给出这样的列表
Clear[a, b, c, d, e, f];
lst = {{a, b}, {c, d}, {e, f}};
Run Code Online (Sandbox Code Playgroud)
并假设我有一个这样定义的函数:
foo[x_,y_]:=Module[{},...]
Run Code Online (Sandbox Code Playgroud)
我想将此功能应用于列表,所以如果我输入
Map[foo, lst]
Run Code Online (Sandbox Code Playgroud)
这给了
{foo[{a, b}], foo[{c, d}], foo[{e, f}]}
Run Code Online (Sandbox Code Playgroud)
我想要它出来
{foo[a, b], foo[c, d], foo[e, f]}
Run Code Online (Sandbox Code Playgroud)
所以它有效.
做这个的最好方式是什么?假设我无法修改函数foo []定义(假设它是内置函数)
我现在只知道两种方式
Map[foo[#[[1]], #[[2]]] &, lst]
{foo[a, b], foo[c, d], foo[e, f]}
Run Code Online (Sandbox Code Playgroud)
(太多的工作),或
MapThread[foo, Transpose[lst]]
{foo[a, b], foo[c, d], foo[e, f]}
Run Code Online (Sandbox Code Playgroud)
(减少输入,但需要先转置)
问题:还有其他更好的方法吗?我看了看其他地图和它的朋友,我看不到比我拥有的更直接的功能.
abc*_*bcd 14
您需要Apply在Level1或它的缩写形式,@@@
foo@@@lst
{foo[a, b], foo[c, d], foo[e, f]}
Run Code Online (Sandbox Code Playgroud)
一种可能的方式是改变的每个元素的头lst从List到foo:
foo @@ # & /@ lst
{foo[a, b], foo[c, d], foo[e, f]}
Run Code Online (Sandbox Code Playgroud)
只是报告这两种方法的令人费解的性能测试(@@@,@@ # & /@):
T = RandomReal[{1,100}, {1000000, 2}];
H[F_Symbol, T_List] :=
First@AbsoluteTiming[F @@@ T;]/First@AbsoluteTiming[F @@ # & /@ T;]
Table[{ToString[F], H[F, T]}, {F, {Plus, Subtract, Times, Divide, Power, Log}}]
Out[3]= {{"Plus", 4.174757},
{"Subtract", 0.2596154},
{"Times", 3.928230},
{"Divide", 0.2674164},
{"Power", 0.3148629},
{"Log", 0.2986936}}
Run Code Online (Sandbox Code Playgroud)
这些结果不是随机的,但对于非常不同的数据大小大致成比例.
@@@是更快大约3-4倍Subtract,Divide,Power,Log 而@@ # & /@更快的4倍Plus,并Times引起其他问题,这些问题(作为一个可以相信)有可能会稍微
通过下面的评测澄清:
Attributes@{Plus, Subtract, Times, Divide, Power, Log}
Run Code Online (Sandbox Code Playgroud)
只有Plus和Times具有属性Flat和Orderless,而只有剩下的中Power(这似乎相对最有效的存在)也有一个属性 OneIdentity.
编辑
对观察到的性能提升的可靠解释(感谢Leonid Shifrin的评论)应该采用不同的方式.
默认情况下MapCompileLength -> 100,我们可以检查评估SystemOptions["CompileOptions"].要重置Map的自动编译,我们可以评估:
SetSystemOptions["CompileOptions" -> "MapCompileLength" -> Infinity]
Run Code Online (Sandbox Code Playgroud)
现在我们可以通过再次评估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}}
Run Code Online (Sandbox Code Playgroud)
有了这些结果,我们可以得出结论,一般来说Yoda的方法(@@@)是最有效的,而Andrei提供的方法更好Plus,Times因为自动编译Map允许更好的(@@ # & /@)性能.
| 归档时间: |
|
| 查看次数: |
1249 次 |
| 最近记录: |