【问题标题】:Mapping two argument function in Mathematica在 Mathematica 中映射两个参数函数
【发布时间】:2011-05-29 13:44:33
【问题描述】:

我要存档:

Map2[f,{a,b,c,d}]
{f[a,b], f[b,c], f[c,d]}

但由于某种原因,我只能想到迭代方法。

函数式的方式是什么?

编辑:

使用它来生成图形示例。如果给出了数字列表,下面会生成按顺序访问所有节点意味着什么的图表。

例如:

Map2 = # @@@ Partition[#2, 2, 1] &;
MG[elems_] := Graph[Map2[DirectedEdge, elems]]
nrs = RandomInteger[{1, 15}, 20]
MG[nrs]

{10,13,9,7,13,3,5,1,15,10,15,6,14,3,1,2,11,4,8,5}

径向布局:

【问题讨论】:

  • @d00b 它必须是; Graph 不在 v7 中。
  • @d00b:是的,这个用例适用于 Mathematica 8。尽管请注意,这个问题本身并不是特定于版本的。更有理由欣赏好的答案。

标签: wolfram-mathematica


【解决方案1】:

最简单的:

Map2 = # @@@ Partition[#2, 2, 1] &;

或者,可能使用较少的内存,但运行速度有点慢:

Map2[f_, lst_] := Developer`PartitionMap[f @@ # &, lst, 2, 1]

另外,请注意DifferencesAccumulate,它们是相关的。


其他方式:

Inner[#, Most@#2, Rest@#2, List] &

请注意,List 可能是一个不同的函数。

MapThread[#, {Most@#2, Rest@#2}] &

Most@MapThread[#, {#2, RotateLeft@#2}] &

Rest@MapThread[#, {RotateRight@#2, #2}] &

Table[# @@ #2[[i ;; i + 1]], {i, Length@#2 - 1}] &

现在,时间安排。我会使用Timo's timeAvg

f1 = # @@@ Partition[#2, 2, 1] &;
f2[f_, lst_] := Developer`PartitionMap[f @@ # &, lst, 2, 1]
f3 = Inner[#, Most@#2, Rest@#2, List] &;
f4 = MapThread[#, {Most@#2, Rest@#2}] &;
f5 = Most@MapThread[#, {#2, RotateLeft@#2}] &;
f6 = Table[# @@ #2[[i ;; i + 1]], {i, Length@#2 - 1}] &;

timings = 
  Table[
   list = RandomReal[99, 10^i];
   func = Plus;
   timeAvg[#[func, list]] & /@ {f1, f2, f3, f4, f5, f6},
   {i, 6}
  ];

TableForm[timings, 
 TableHeadings -> {10^Range@6, {"f1", "f2", "f3", "f4", "f5", "f6"}}]

ListLogPlot[timings\[Transpose], Joined -> True]

表格左侧的数字是每次运行的实数列表的长度。

请注意,图表是对数的。

以下是处理最长列表 (1,000,000) 时使用的内存字节数:


完成上述计时后,我发现我可以通过消除 Apply (@@) 使 f6 更快。它现在显然是较长列表中最快的。我不会将它添加到上表中,因为它已经足够宽了,但这里是函数及其时间:

f7 = Table[#2[[i]] ~#~ #2[[i + 1]], {i, Length@#2 - 1}] &;

【讨论】:

  • @Margus,我很高兴有帮助。我的回答还没有结束。还有其他方法,我想添加时间,请稍后再回来查看。
  • @Mr.我将把你所有的功能添加到我的答案中作为报复:)
  • @Mr.我对此感到冒犯:)。你忘了把我唯一的贡献包括在测试中。我赢了吗? :)
  • @Mr.在我的评分中,使用Inner的最快,被删除的是第二。
  • @belisarius,已更正。您使用相同的代码还是不同的代码?我想知道Table 在 v8 中是否更慢。
【解决方案2】:

正如Mathematica cookbook 中解释的那样,将函数映射到移动子列表可以优雅地使用ListConvole 函数解决:

Map2[f_, l_List] := ListConvolve[{1, 1}, l, {-1, 1}, {}, #2 &, f]

In[11]:= Map2[f, {a, b, c, d}]
Out[11]= {f[a, b], f[b, c], f[c, d]}

Mr.Wizard 在这里,根据 sakra 的要求添加比较时间。

【讨论】:

  • 我知道我忘记了什么。 :-)
  • (grumble mode) 我自己投了这个票,因为它很有帮助,但它不是这里最好的方法。事实上,它比我给出的任何选项都慢。没有什么不利于你的sakra,但我认为它不应该排名那么高。
  • @Mr.Wizard 你能把 ListConvole 选项添加到你的时序测试图中吗?
  • sakra,我可以编辑您的帖子以包含比较图表,还是您不希望我不这样做?
  • 完成。观察到Map2 比简单的f1 慢。 f3 通常比 f1 快,但它在 10^5 列表中有一个奇怪的气泡。 f7 开始很慢,但是一旦启动自动编译,它很容易是最快的。
【解决方案3】:

我喜欢:

Map2[f_, l_List]:= MapThread[f, {Most@l, Rest@l}]

In[988]:= Map2[f,{a,b,c,d}]
Out[988]= {f[a,b],f[b,c],f[c,d]}

【讨论】:

    【解决方案4】:

    我最近重新阅读了您的问题并看到了您的Graph[ ] 申请。

    我认为这样做的自然方法是:

    f[l_] := Graph[Thread[Most@l -> Rest@l]]
    

    所以

    f[{10, 13, 9, 7, 13, 3, 5, 1, 15, 10, 15, 6, 14, 3, 1, 2, 11, 4, 8, 5}]  
    

    【讨论】:

    • +1 用于阅读更新后的问题,并提供了一个很好的解决方案。
    【解决方案5】:

    按照 belisarius 的引导,并处理您的 Graph 应用程序,这应该会快一点:

    f = Inner[Rule, Most@#, Rest@#, Composition[Graph, List]] &;
    

    【讨论】:

    • 我认为,作为当前显示有向图形的应用程序,速度对那个的重要性是值得怀疑的。一个巨大的图表几乎难以辨认:)。 +1
    • @belisarius 我认为Graph 用于其他东西,而不仅仅是显示。不?无论如何感谢您的+1。我更喜欢你的解决方案。
    • 从问题上下文看来,显示是目标,但您可能是对的。
    【解决方案6】:

    哇,我看到了其他解决方案,它们看起来相当复杂和令人困惑。这更容易理解,至少如果您喜欢更实用的方法:

    MapApplyImpl[fun_] := Function[{args}, Apply[fun, args]]
    MapApply[fun_, argList_] := Map[MapApplyImpl[fun], argList]
    

    还有一个用法示例:

    ff := Function[{t, phi}, t*phi]
    MapApply[ff, {{0, Pi/4}, {(Pi/4)/(10^3) , 0}, {(2*Pi/(10^3)), 
       Pi/4}}]
    

    【讨论】:

      猜你喜欢
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      相关资源
      最近更新 更多