这有标准功能吗?

时间:2010-11-03 00:14:11

标签: wolfram-mathematica

在Mathematica中可能有内置函数或更好更快的方法

func[l_, g_, f_] := g @@ f @@@ Transpose[{Most[l], Rest[l]}]

可以用来做这样的事情

l = {a, b, c, d}
func[l, Plus, (#1 - #2)^2 &]

我不知道这种功能的正确名称。折叠拉链类型的东西。

更新 很多解决方案。谢谢大家。

使用

Partition[l, 2, 1] 

而不是

Transpose[{Most[l], Rest[l]}] 

肯定会让它更清晰。

我试图在函数上运行时序,但是我得到了奇怪的结果:

func1[l_, g_, f_] := g @@ f @@@ Transpose[{Most[l], Rest[l]}]
func2[l_, g_, f_] := g @@ f @@@ Partition[l, 2, 1]
func3[l_, g_, f_] := g @@ ListConvolve[{1, 1}, l, {-1, 1}, {}, Times, f]
func4[l_, g_, f_] := g @@ Thread[f[Most@l, Rest@l]]
func5[l_, g_, f_] := g @@ f /@ Partition[l, 2, 1]
func6[l_, g_, f_] := g @@ Thread[f[Most[l], Rest[l]]]
func7[l_, f_, g_] := Inner[f, Sequence @@ Partition[l, Length[l] - 1, 1], g]
func8[l_, g_, f_] := g @@ MapThread[f, Partition[l, Length[l] - 1, 1]]
functions = {func1, func2, func3, func4, func5, func6, func7, func8}

input = Table[ToExpression["x" <> ToString[i]], {i, 1, 1000000}];
inputs = Table[Take[input, i*100000], {i, 1, 10}];

Table[
  If[i == j == 0, "",
  If[j == 0, functions[[i]],
  If[i == 0, Length[inputs[[j]]],
    Timing[functions[[i]][inputs[[j]]]][[1]]]]], 
    {i, 0, Length[functions]}, {j, 0, Length[inputs]}] // Transpose // TableForm

5 个答案:

答案 0 :(得分:6)

如果您想要完全复制func功能的内容,我唯一能想到的就是将Transpose[Most[l],Rest[l]]替换为Partition

func2[l_,g_,f_]:=g@@f@@@Partition[l,2,1]

如果你真的想要“内置”的东西,那么你可以通过攻击来攻击ListConvolve

func3[l_,g_,f_]:=g@@ListConvolve[{1,1},l,{-1,1},{},Times,f]

检查所有这些是否有效:

Through[{func,func2,func3}[l,Plus,(#1-#2)^2&]]
Out[19]= {(a-b)^2+(b-c)^2+(c-d)^2,(a-b)^2+(b-c)^2+(c-d)^2,(a-b)^2+(b-c)^2+(c-d)^2}

最后,如果这是您正在寻找的答案,我建议您按Total[Differences[l]^2]计算它

Out[14]= (-a+b)^2+(-b+c)^2+(-c+d)^2 

答案 1 :(得分:4)

每当你看到像f@@@Transpose[{args}]这样的内容时,你应该想到Thread[]。这在The semantics of Mathematica's Thread function中进行了讨论。

所以我能做的最好的就是

func[l_, g_, f_] := g @@ Thread[f[Most[l], Rest[l]]]

但是Most[l], Rest[l]结构仍然看起来很丑陋且效率低下。可能有一种更有效的方法 - 但也许这可以像在Mathematica中那样紧凑。

答案 2 :(得分:3)

相当于(不是说它更好):

      func[l_, g_, f_] := g @@ Thread[f[Most@l, Rest@l]]

或几乎

      func[l_, g_, f_] := g @@ f /@ Partition[l, 2, 1]

但最后一个需要

      func[l, Plus, (#[[1]] + #[[2]])^2 &]

这显然是次等的

答案 3 :(得分:3)

这不是一个答案,而是一个更好的计时例程的建议。此

 timeAvg[func_] := Module[{
    x = 0, y = 0, timeLimit = 0.1, p, q, 
    iterTimes = Power[10, Range[0, 10]]},
   Catch[
     If[(x = First[Timing[(y++; Do[func, {#}]);]]) > timeLimit,
        Throw[{x, y}]
        ] & /@ iterTimes
     ] /. {p_, q_} :> p/iterTimes[[q]]
   ];
Attributes[timeAvg] = {HoldAll};

会很快计算出平均运行时间,例如,

timeAvg@func1[l, Plus, (#1 - #2)^2 &]

l尝试不同的长度会得到以下结果 Timing 其中N是l中元素的数量。 Thread[]是明显的赢家。

答案 4 :(得分:2)

我认为这只是一个广义的内积(广义点积),以Transpose / Most / Rest位为模,所以你也可以使用Inner

func[lis_, f_, g_] := Inner[f, Sequence@@Partition[list, Length[lis]-1, 1], g]

In[90]:= func[l,Plus,(#-#2)^2&]
Out[90]= (a - b)^2 + (b - c)^2 + (c - d)^2

还有MapThread,我提到完整性:

func2[lis_, g_, f_] := g @@ MapThread[f, Partition[lis, Length[lis]-1, 1]]

In[94]:= func2[l, Plus, (# - #2)^2 &]
Out[94]= (a - b)^2 + (b - c)^2 + (c - d)^2

如果您总是在列表中产生差异,DifferencesListConvolve可能会更快,正如其他人所提到的那样。

与Perl一样,TMTOWTDI in Mathematica也是如此,因为你问题的所有答案都显示出来了!