有这个标准功能吗?

发布于 2024-09-30 20:09:28 字数 1404 浏览 3 评论 0原文

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

There is probably built-in function or a better and faster way to do this in Mathematica

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

which can be used to do things like this

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

I don't know the proper name for this kind of function. Something in a fold-zip genre.

UPDATE
Lot's of solutions. Thanks to everyone.

Using

Partition[l, 2, 1] 

instead of

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

definitely makes it clearer.

I've tried to run timings on the functions, but I get strange results:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

恋你朝朝暮暮 2024-10-07 20:09:28

如果您想要完全复制 func 功能的东西,我能想到的唯一漂亮的方法是将 Transpose[Most[l],Rest[l]] 替换为 < code>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 

If you want something that exactly duplicates the functionality of your func, the only prettyfication I can think of is replacing Transpose[Most[l],Rest[l]] with Partition:

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

If you really want something "built in", you could hack on some ListConvolve for kicks

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

Checking that all these work:

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}

Finally, if this is the answer you are looking for, I would suggest computing it by Total[Differences[l]^2]

Out[14]= (-a+b)^2+(-b+c)^2+(-c+d)^2 
烂柯人 2024-10-07 20:09:28

每当您看到类似 f@@@Transpose[{args}] 之类的内容时,您应该想到 Thread[]Mathematica Thread 函数的语义对此进行了讨论。

所以我能做的最好的事情就是

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

,但是 Most[l], Rest[l] 构造仍然看起来丑陋且低效。可能有一种更有效的方法来做到这一点 - 但也许这是 Mathematica 中所能达到的最紧凑的方法。

Whenever you see something like f@@@Transpose[{args}] you should think of Thread[]. This was discussed in The semantics of Mathematica's Thread function.

So the best I could do was

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

but the Most[l], Rest[l] construction still seems ugly and inefficient. There is probably a more efficient way to do it - but maybe this is as compact as it can get in Mathematica.

不醒的梦 2024-10-07 20:09:28

相当于(不是说更好):

      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 &]

哪个明显较差

Equivalent to (not saying it's better):

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

Or almost

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

But this last one needs

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

Which is clearly inferior

情深如许 2024-10-07 20:09:28

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

 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 的不同长度给出以下结果
计时
其中 N 是 l 中的元素数量。 Thread[] 是明显的赢家。

This is not an answer but a suggestion for a better timing routine. This

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

will calculate an average run time quite quickly, e.g.,

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

Trying out different lengths for l gives the following result
Timing
where N is the number of elements in l. Thread[] is the clear winner.

粉红×色少女 2024-10-07 20:09:28

我认为这只是一个广义内积(广义点积),以 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
Mathematica 也是如此,正如您问题的所有答案所示!

I think that's just an generalized inner product (generalized dot product), modulo the Transpose/Most/Rest bit, so you could also just use 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

There's also MapThread, which I mention for completeness:

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

If you're always making differences out of the list, Differences or ListConvolve could be faster, as others have mentioned.

Like Perl, TMTOWTDI in
Mathematica too, as all the answers to your question show!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文