2011-12-23 84 views
0

我一直在學習使用Map more(成爲更多功能的程序員)。它看起來像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的結果中去除{})。

所以我想,那爲什麼不一直加這個額外的{}並最終刪除它? 這樣,我不必擔心我的Map'ing函數是不是像上面例子那樣的列表?

所以,我的例子將全部變成這樣:

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

這樣,代碼將在一切工作和我沒有,如果使用地圖前進行專項檢查什麼,我碰巧申請地圖是一個列表或不是。

問題是:上述問題是否適合專家的解決方案,還是有更好的方法來處理這個問題?

+0

我不得不承認,我不明白你的動機是什麼,問這個問題。爲什麼你會嘗試將Map映射到不是列表的東西? – 2011-12-23 07:56:05

+1

@David Zaslavsky一個人可能最終想要將Map映射到不同於列表的其他東西上,但這種情況非常少見,而且在與此問題討論的情況不同的情況下完成。一個典型的例子就像'Map [f,myContainerA [myContainerB [1,2,3], myContainerC [4,5,6]],{2}]',儘管在這種情況下我通常使用規則。 – 2011-12-23 12:14:36

+0

也許我誤解了你的問題,但我的方法沒有回答嗎?如果不是,你可以嘗試以不同的方式解釋你想要的嗎?在我看來,我的建議確實如你所願。 – acl 2011-12-23 12:56:52

回答

2

這僅發生在工作列表上的,因爲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 
*) 
2

我看到幾個不同的問題

  1. 有哪些不同的方式來Map?毫不奇怪,因爲列表是Mathematica操作的基礎,所以有很多方法可以對它們進行轉換。然而,我沒有任何直接告訴Mathematica的方法,給出f{l1, l2, ...}給我{[email protected], 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]:=somethingf[a_List]給出了f/@a結果即使的一些元素沒有頭AtomicType - 即可列功能不要驗證列表中的所有元素都有f的轉換規則。如果你關心這個,你需要單獨定義f[a:{_AtomicType..}]:=f/@a而不是你的功能Listable

另外,@納賽爾,它看起來像你的第一個例子中的行爲是因爲Map[f,a_AtomicType]返回a。另請注意,Map可以映射任意表達式,而不僅僅是List

3

也許我不是在這裏理解你的意圖,但如果你正在尋找Map函數只是列表中的一個特定條目,那麼MapAt是你正在尋找的函數。示例:

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

這裏,該函數僅適用於列表中的第一個元素。

+0

好點,我以爲他只是想要一種能夠說'Map [f,l]'的方式,並且無論'l'是列表式還是原子式,它都能正常工作。但是,也許你的解釋是正確的。 – acl 2011-12-23 02:37:50

+0

其實我知道MapAt,但它是導致同樣的事情。如果我想將NumberForm應用於一個條目,則必須使用MapAt,如果我想將NumberForm應用於列表,則使用Map。所以回到原點:)我詢問添加{}的原因是爲了查看兩種情況下是否可以使用一種方法。 – Nasser 2011-12-23 03:19:49

2

這似乎是一個奇怪的問題。爲什麼寫[email protected][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}] 
相關問題