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}}