如何将函数映射到列表中的一个条目上?
我一直在学习更多地使用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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
也许我不理解您的意图,但如果您正在查找
Map
列表中特定条目的函数,那么MapAt
是您要查找的函数。示例:此处,该函数仅应用于列表中的第一个元素。
Perhaps I'm not understanding your intent here, but if you're looking
Map
a function on just a particular entry in a list, thenMapAt
is the function you're looking for. Example:Here, the function has been applied to only the first element in the list.
这之所以有效,是因为
NumberForm
适用于列表:给出
Map[f, {{a, b, c}}]
简单地映射f
到First[{{a,b,c}}]
,即到{a,b,c}
;所以你得到f[{a,b,c}]
。因此不幸的是,添加
{}
通常不起作用。一个简单的方法是定义
从哪里
给定
,但是这不允许使用 Map[f,expr,levelspec] 形式(但是它很容易实现)。
这也适用于这种情况:
This only happens to work because
NumberForm
works on lists:gives
Map[f, {{a, b, c}}]
simply mapsf
ontoFirst[{{a,b,c}}]
, namely, onto{a,b,c}
; so you getf[{a,b,c}]
.So unfortunately adding
{}
will not work in general.A simple way to do this is to define
whence
give
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:
这似乎是一个奇怪的问题。当你可以只写
f @ x
时,为什么还要写First@Map[f, { x } ]
呢?Map
的第二个参数怎么可能是任一形式?也许您会发现从末尾开始按级别映射的价值:
要小心这一点,就好像列表元素不是原子的一样,您会得到意想不到的结果。
或者,您也可以这样写:
This seems like an odd question. Why write
First@Map[f, { x } ]
when you can just writef @ 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:
Be careful with this, as if the list elements are not atomic, you will get unexpected results.
Alternatively, you might write:
我看到了几个不同的问题
Map
有哪些不同的方法?毫不奇怪,因为列表是 Mathematica 操作的基础,所以有很多方法可以转换它们。但是,我没有任何直接的方法可以告诉 Mathematica,给定f
和{l1, l2, ...}
给我{f@l1,l2,...}
。如果您想将f
应用于l
的第一个元素(例如,在将 f 应用于所有 l 之前进行测试),您也可以执行f/@ l[[1;;1]]
。 (编辑 @yoda 提到MapAt
有这种行为,可以指定一组应该映射的位置)。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
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, givenf
and{l1, l2, ...}
to give me{f@l1, l2, ...}
. If you want to applyf
to the first element ofl
(for example, to test before applying f to all of l) you can also dof/@l[[1;;1]]
. (edit @yoda mentions thatMapAt
has this behavior, one can specify a set of positions where one should map).Listable
attribute. Then if we define:f[a_AtomicType]
,f[a:{_AtomicType..}]
gives the results off/@a
Edit -- Actually, given
f[a_AtomicType]:=something
,f[a_List]
gives the results off/@a
even if some elements of a don't have headAtomicType
-- ie Listable functions don't verify that all elements of the list have a transformation rule in terms off
. If you care about this you would need to separately definef[a:{_AtomicType..}]:=f/@a
and not make your functionListable
.Also, @Nasser, it looks like the behavior in your first example is because
Map[f,a_AtomicType]
returnsa
. Also note thatMap
can map over expressions with any head, not justList
.