如何在列表中的一个条目上映射函数?

时间:2011-12-23 01:22:44

标签: wolfram-mathematica

我一直在学习更多地使用Map(成为更多功能的程序员)。看起来Map想要一个列表作为应用函数的表达式。如果表达式不是列表,则表示不满意。

我在这个例子中使用NumberForm来说明我的意思:

我可以在整个列表中映射NumberForm确定:

data = {1, 2, 3}
Map[NumberForm[#, {3, 2}] &, data]

但是,如果我尝试将其映射到列表中的某个特定元素,请说上面的第一个,它不起作用

data = {1, 2, 3}
Map[NumberForm[#, {3, 2}] &, data[[1]] ]

返回的结果未格式化。与原始数据相同。即我回到'1'而不是'1.00',就像在其他例子中一样。

要解决这个问题,我添加了额外的{}

data = {1, 2, 3}
Map[NumberForm[#, {3, 2}] &, {data[[1]]} ]

现在可以使用,(只需要使用{}从结果中删除First)。

所以我想,为什么不一直添加这个额外的{}并最终删除它? 这样,我不必担心我的Maping功能是不是像上面那样的列表?

所以,我的例子都会变成这样:

data = {1, 2, 3}
First@Map[NumberForm[#, {3, 2}] &, { data } ]
First@Map[NumberForm[#, {3, 2}] &, { data[[1]] } ]

通过这种方式,代码将适用于所有内容,如果我正在应用Map的地址与列表不同,我无需在使用Map之前进行特殊检查。

问题是:上述内容对专家来说是否是一个好的解决方案,还是有更好的方法来解决这个问题?

4 个答案:

答案 0 :(得分:3)

也许我在这里不理解你的意图,但是如果你在列表中的某个特定条目上查找Map函数,那么MapAt就是你正在寻找的函数。例如:

MapAt[NumberForm[#, {3, 2}] &, data, 1]
Out[1]= {1.00,2,3}

此处,该函数仅应用于列表中的第一个元素。

答案 1 :(得分:2)

这恰好可行,因为NumberForm适用于列表:

NumberForm[{1, 2, 3}, {3, 2}]

给出

{1.00, 2.00, 3.00}

Map[f, {{a, b, c}}]只需将f映射到First[{{a,b,c}}],即映射到{a,b,c};所以你得到f[{a,b,c}]

所以不幸的是,添加{}通常无效。

一种简单的方法是定义

ClearAll[map]
map[f_, head_[els__]] := Map[f, head[els]]
map[f_, el_] := f[el]

何处

map[f, {a, b, c}]
map[f, a]

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

然而,这不允许使用Map[f,expr,levelspec]形式(但这很容易实现)。

这也适用于这种情况:

map[f, g[a, b, c]] == Map[f, g[a, b, c]]
(*
True
*)

答案 2 :(得分:2)

我看到了几个不同的问题

  1. Map有哪些不同的方法?毫不奇怪,因为列表是Mathematica操作的基础,所以有很多方法可以对它们进行转换。但是,由于f{l1, l2, ...}给了我{f@l1, l2, ...},所以我没有任何直接的方法告诉M​​athematica。如果您要将f应用于l的第一个元素(例如,在将f应用于所有l之前进行测试),您也可以执行f/@l[[1;;1]]。 (编辑@yoda提到MapAt有这种行为,可以指定一组应该映射的位置。)
  2. 如何处理实现Composite模式的操作数(即,是t类型的元素还是t类型的元素列表)?在Mathematica中执行此操作的自然方法是为操作员提供Listable属性。然后,如果我们定义:f[a_AtomicType]f[a:{_AtomicType..}]会给出f/@a
  3. 的结果

    编辑 - 实际上,给定f[a_AtomicType]:=somethingf[a_List]给出f/@a的结果,即使a的某些元素没有头AtomicType - 即可列表函数不要验证列表中的所有元素都有f方面的转换规则。如果您关心这一点,则需要单独定义f[a:{_AtomicType..}]:=f/@a,而不是让您的函数Listable

    另外,@ Nasser,看起来你的第一个例子中的行为是因为Map[f,a_AtomicType]返回a。另请注意,Map可以使用任何头部映射表达式,而不仅仅是List

答案 3 :(得分:2)

这似乎是一个奇怪的问题。为什么在写First@Map[f, { x } ]时写f @ x

Map的第二个参数可能是哪种形式?

也许你会从最后的级别找到映射值:

Map[f, {x, y, z}, {-1}]

Map[f, x, {-1}]

小心这一点,就好像列表元素不是原子元素一样,你会得到意想不到的结果。

或者,你可以写:

data = {1, 2, 3};

data /. n_?NumberQ :> NumberForm[n, {3, 2}]

data[[1]] /. n_?NumberQ :> NumberForm[n, {3, 2}]