【问题标题】:Mathematica Map questionMathematica 地图问题
【发布时间】:2010-11-08 18:39:09
【问题描述】:

原问题:

我知道 Mathematica 有一个内置的 map(f, x),但是这个函数是什么样的呢?我知道您需要查看列表中的每个元素。

有什么帮助或建议吗?

编辑(由 Jefromi,从 Mike 的 cmets 拼凑而成):

我正在开发一个程序,该程序需要在地图之类的列表中移动,但我不允许使用它。我也不允许使用 Table;我需要在没有其他功能的帮助下浏览列表。我正在开发一个递归版本,我有一个空列表,但是在一个包含项目的列表中移动是行不通的。这是我的第一个案例:newMap[#, {}] = {}(空列表的映射只是一个空列表)

【问题讨论】:

  • 你说的“这个函数是什么样子的”是什么意思?我假设你在问Map;你看过the documentation吗?有什么让你困惑的地方吗?
  • 我不确定您在寻找什么。您是否正在寻找Map(参数布局)的签名,它是如何运作的,或者它是如何实现的?
  • 我正在寻找它是如何运作的,如何在mathematica中递归地移动一个列表,尤其是Map中的第一个参数是什么,如果我写的是我自己知道Map( __, List) 我会在第一个括号里放什么?
  • @Mike:啊哈!提问的一般建议:询问您真正想做什么。
  • @Mike:如果不使用 any 函数,你不可能做到这一点;一切都是函数,甚至 FirstLastPart。如果您可以编辑您的问题以准确说明您需要做什么以及您的限制是什么,我们可以提供有用的答案,而不是试图猜测。此外,如果您的评论涉及答案,您可以评论答案本身,而不是您的问题。

标签: map wolfram-mathematica


【解决方案1】:

我发布了一个递归解决方案,但后来决定将其删除,因为从 cmets 这听起来像是一个家庭作业问题,而且我通常是一个教鱼的人。

您正在使用您的定义newMap[f_, {}] := {} 找到递归解决方案。

Mathematica 的模式匹配是您的朋友。考虑如何实现newMap[f_, {e_}] 的定义,并从那里实现newMap[f_, {e_, rest___}]

最后一个提示:一旦您可以定义最后一个函数,您实际上就不需要{e_} 的情况。

更新

根据您的 cmets,也许这个示例将帮助您了解如何应用任意函数:

func[a_, b_] := a[b]

In[4]:= func[Abs, x]
Out[4]= Abs[x]

解决方案

既然 OP 钓到了一条鱼,可以这么说,(恭喜!)这里有两个递归解决方案,以满足任何围观者的好奇心。第一个可能是我认为“惯用”的 Mathematica:

map1[f_, {}] := {}
map1[f_, {e_, rest___}] := {f[e], Sequence@@map1[f,{rest}]}

这是不充分利用模式匹配的方法,这基本上是 OP 的最终结果:

map2[f_, {}] := {}
map2[f_, lis_] :=  {f[First[lis]], Sequence@@map2[f, Rest[lis]]}

{f[e], Sequence@@map[f,{rest}]} 部分可以用多种等价方式表示,例如:

  • Prepend[map[f, {rest}], f[e]]
  • Join[{f[e]}, map[f, {rest}](@Mike 使用了这种方法)
  • Flatten[{{f[e]}, map[f, {rest}]}, 1]

我将留给读者去思考更多,并思考其中大多数对性能的影响 =)

最后,为了好玩,这里是一个程序版本,尽管写它让我有点恶心:;-)

map3[f_, lis_] :=
 (* copy lis since it is read-only *)
 Module[{ret = lis, i},
  For[i = 1, i <= Length[lis], i++,
   ret[[i]] = f[lis[[i]]]
   ];
  ret
  ]

【讨论】:

  • _Blank,并且匹配任何表达式。 f_ 实际上只是将匹配的任何内容分配给函数定义中的局部变量 f。阅读"Introduction to Patterns" 教程可能会有所帮助。
  • 内置的Map 将映射到任何头部,所以可能更像newMap[f_, lst_[a_, b__]] := ... 的东西更合适。在这个方法中可以使用最后一个技巧,即使用 Sequence@@,可以将其缩写/混淆为 ##&@@
  • + 不加入列表,它始终是 Mathematica 中的算术运算符。推荐阅读:"List Manipulation"
  • Mathematica 中的某些函数是“Listable”,这意味着它们会自动将自身映射到任何列表参数上。比较评估Abs[{1, -1, 2}]f[{1, 2, 3}] 的结果。如果您的解决方案是正确的,maps[f, {1,2,3}] 将给出{f[1],f[2],f[3]},但我相信它会改为输出{f[1], f[{2,3}]} 并且可能会出现一些错误。
  • 在您的函数中,Rest[x] 正确地给出了列表的“其余部分”,然后您需要将fun 映射到它上面,并将其加入第一部分。但是,您已经有了将fun 映射到列表的函数,所以...
【解决方案2】:

为了回答您在 cmets 中提出的问题,Map 中的第一个参数是一个接受单个参数的函数。这可以是一个纯函数,也可以是一个已经只接受单个参数的函数的名称,例如

In[1]:=f[x_]:= x + 2
       Map[f, {1,2,3}]
Out[1]:={3,4,5}

至于如何用您自己设计的递归函数替换Map……按照 Jefromi 的示例,我不会给出太多内容,因为这是家庭作业。但是,您显然需要某种方式对列表的一部分进行操作,同时为 map 函数的递归部分保持列表的其余部分完好无损。正如他所说,Part 是一个很好的起点,但我会看看它引用的其他一些函数,看看它们是否更有用,比如FirstRest。另外,我可以看到Flatten 的用处。最后,您需要一种结束递归的方法,因此学习如何约束模式可能很有用。顺便说一句,这可以在一行或两行中完成,具体取决于您是否为地图创建第二个定义(更简单的方法)。

提示:现在你已经有了结束条件,你需要回答三个问题:

  1. 如何从列表中提取单个元素,
  2. 如何引用列表的其余元素,以及
  3. 如何将其重新组合在一起?

想一想流程中的一个步骤以及在该步骤中您需要完成什么会有所帮助。

【讨论】:

  • 鉴于不允许使用该表,First/Rest 在这里绝对是不错的习语。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 2014-03-12
相关资源
最近更新 更多