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

发布于 2024-12-22 11:40:28 字数 1004 浏览 3 评论 0原文

我一直在学习更多地使用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 从结果中删除 {})。

所以我想,那为什么不一直添加这个额外的 {} 并最终删除它呢? 这样,我就不必担心我的映射函数是否恰好不是上面示例中的列表?

因此,我的示例将变成这样:

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

这样,代码将适用于所有内容,并且我不必在使用 Map 之前进行特殊检查,如果我碰巧应用 Map 的是列表或不是列表。

问题是:对于专家来说,上述解决方案看起来不错,还是有更好的方法来处理这个问题?

I have been learning to use Map more (to become more functional programmer). It looks like Map wants a list as the expression to apply the function to. If the expression is not a list, then it is not happy.

I use NumberForm in this example to illustrate what I mean:

I can Map NumberForm on the whole list ok:

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

But if I try to Map it to some specific element in the list, say the first one in the above, it does not work

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

The result returned is NOT formatted. Same as original data. i.e I get back '1' and not '1.00' as in the other examples.

To solve, I added extra {}

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

it works now, (just need to remove the {} from the result using First).

So I thought, then why not add this extra {} all the time and remove it in the end?
This way, I do not have to worry if what I am Map'ing function to happened to be not a list like in the above example?

So, my examples will all becomes like this:

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

This way, code will works on everything and I do not have to make special check before using Map if what I happened to be applying Map to is a list or not.

Question is: Does the the above look an OK solution for the experts, or is there a better way to handle this?

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

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

发布评论

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

评论(4

梦回梦里 2024-12-29 11:40:28

也许我不理解您的意图,但如果您正在查找 Map 列表中特定条目的函数,那么 MapAt 是您要查找的函数。示例:

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

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

Perhaps I'm not understanding your intent here, but if you're looking Map a function on just a particular entry in a list, then MapAt is the function you're looking for. Example:

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

Here, the function has been applied to only the first element in the list.

红衣飘飘貌似仙 2024-12-29 11:40:28

这之所以有效,是因为 NumberForm 适用于列表:

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

给出

{1.00, 2.00, 3.00}

Map[f, {{a, b, c}}] 简单地映射 fFirst[{{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
*)

This only happens to work because NumberForm works on lists:

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

gives

{1.00, 2.00, 3.00}

Map[f, {{a, b, c}}] simply maps f onto First[{{a,b,c}}], namely, onto {a,b,c}; so you get f[{a,b,c}].

So unfortunately adding {} will not work in general.

A simple way to do this is to define

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

whence

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

give

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

However this does not allow for the Map[f,expr,levelspec] form (which however is easy enough to implement).

This also works in this case:

map[f, g[a, b, c]] == Map[f, g[a, b, c]]
(*
True
*)
傾城如夢未必闌珊 2024-12-29 11:40:28

这似乎是一个奇怪的问题。当你可以只写 f @ x 时,为什么还要写 First@Map[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}]

This seems like an odd question. Why write First@Map[f, { x } ] when you can just write f @ x?

How does it come to be that the second argument of Map may be either form?

Perhaps you would find value in mapping by levels from the end:

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

Map[f, x, {-1}]

Be careful with this, as if the list elements are not atomic, you will get unexpected results.

Alternatively, you might write:

data = {1, 2, 3};

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

data[[1]] /. n_?NumberQ :> NumberForm[n, {3, 2}]
过期以后 2024-12-29 11:40:28

我看到了几个不同的问题

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

编辑-- 实际上,给定 f[a_AtomicType]:=something,即使某些元素,f[a_List] 也会给出 f/@a 的结果一个没有头的AtomicType——即可列表函数不验证列表的所有元素是否都具有f形式的转换规则。如果您关心这一点,则需要单独定义 f[a:{_AtomicType..}]:=f/@a 并且不要使您的函数Listable

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

I see a few different questions

  1. What are the different ways to Map? Not surprisingly, because lists are fundamental to the operation of Mathematica, there are many ways to transform them. However, there isn't any direct way that I can see to tell Mathematica that, given f and {l1, l2, ...} to give me {f@l1, l2, ...}. If you want to apply f to the first element of l (for example, to test before applying f to all of l) you can also do f/@l[[1;;1]]. (edit @yoda mentions that MapAt has this behavior, one can specify a set of positions where one should map).
  2. How to deal with an operand that implements the Composite pattern (ie, is either an element of type t or a list of elements of type t)? The natural way to do this in Mathematica is to give your operator the Listable attribute. Then if we define: f[a_AtomicType], f[a:{_AtomicType..}] gives the results of f/@a

Edit -- Actually, given f[a_AtomicType]:=something, f[a_List] gives the results of f/@a even if some elements of a don't have head AtomicType -- ie Listable functions don't verify that all elements of the list have a transformation rule in terms of f. If you care about this you would need to separately define f[a:{_AtomicType..}]:=f/@a and not make your function Listable.

Also, @Nasser, it looks like the behavior in your first example is because Map[f,a_AtomicType] returns a. Also note that Map can map over expressions with any head, not just List.

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