2、表操做 返回目錄頁
一、引言
二、表的建立與表的測量
Range Table Length Dimensions
三、對錶中元素的處理
Position Part Take Drop Delete First/Last/Rest Select/Reverse/Sort
RotateLeft/RotateRight Flatten Partiton Transpose Append/Prepend Insert/ReplacePart
四、對多個表的處理
Join/Union Complement/Intersection
五、高階函數
Map/MapThread Outer Apply
六、函數對錶的重複做用
Nest/NestList Fold/FoldList
七、字符串和字符
StringLength... Characters/StringJoin ToCharacterCode/FromCharacterCode
html
----------------------------------------------------程序員
一、引言
上面能夠看到,表操做函數有幾十個。如今的MMA表操做函數,已經上千了。
最經常使用的,也就那麼幾十個,並很少。
咱們熟悉MMA的函數,當從表操做函數開始。緣由有幾個:
表是MMA中最經常使用的數據結構。
表操做函數是最經常使用的MMA函數。
咱們學英語,要先很是熟悉最經常使用的220個單詞(Sight Words),同樣,學MMA,要先熟悉這幾十個表操做函數。
除此以外,還有個祕密緣由,在本章的最後。若是急着想知道,就戳吧。
MMA中表之強大,在於表中能夠聽任何表達式。
List[2.4, dog, Sin, "read", {5, 3}, Pi, {}]
{}是空表,empty list。
List[2.4, dog, Sin, "read", {5, 3}, Pi, {}] // TreeForm
MMA中表之強大,更在於,表能夠是多維的。這個維數,能夠從樹形結構上去理解。
----------------------------------------------------
二、表的建立與表的測量
表的建立,只有兩個函數。表的測量,也只有兩個函數。
表的建立的兩個函數是:Range、Table
Range[1, 10, 2]
得:{1, 3, 5, 7, 9}
三個參數分別是:最小、最大、步長。至關於在構建等差數列。
Table[i, {i, 1, 10, 2}]
結果與上面同樣的。能夠看到,{i, 1, 10, 2}中的含義:變量、最小、最大、步長。
第一個參數i位置,能夠聽任何表達式。這個表達式能夠與i有關,也能夠與i無關。
函數設計到這裏,彷佛差很少了。但MMA展現了靈活性:不少參數是能夠省略的。
A、若是步長爲1,能夠省略不寫。
B、若是起始最小值爲1,能夠省略不寫。
C、若是Table中的表達式與變量i無關,變量i能夠省略不寫。
D、終止最大值,永遠不能夠省略。
Range[5]
Table[2i,{i,5}]
Table["哈",{5}]
有沒有找到好玩的感受?MMA這是在偷工減料啊。。不過,不少程序員很喜歡這種偷工減料,由於很好用,並且代碼很簡潔。
Table[i + j, {j, 1, 4}, {i, 1, 2}]
Table[i + j, {j, 1, 4}, {i, 1, 2}] // MatrixForm
Table[i + j, {j, 1, 4}, {i, 1, 2}] // TableForm
Table函數還支持多重循環。外層循環變量(j)要先寫。也就是說,循環變量在Table參數中的順序是有講究的。
Matrix是矩陣。這裏一不當心,就構建出了一個矩陣。表做爲最經常使用的數據,是由於能夠構建不少東西。
表的測量的兩個函數是:Length、Dimensions
很好理解,前者返回表的長度,後者返回表的維數。
Length[{1, a, b}] (*返回3,很好理解*)
Dimensions[{1, a, b}] (*返回{3},很差理解*)
由於表啊,能夠是一維,也能夠是多維。在多維時,能夠是規則的多維(好比矩陣),也能夠是不規則的多維。因此使狀況復雜了。
咱們來細看一下:
lis = {{{1, 2}, {3, 4}, {5, 6}}, {{a, b}, {c, d}, {e, f}}};
lis // TreeForm
lis // Length
lis // Dimensions
lis
Clear[lis];
lis =.;
lis
lis只是給輸入的表起了個名字,能夠理解爲別名。用完了以後,最好取消別名。程序中給出了兩種取消的方法。
給人家取了綽號,不能老叫啊。。老叫不禮貌。
取消了以後,lis就是一個符號,再也不是表的別名了。若是後面一不當心又用了lis,就不容易出錯。
觀察樹形結構,若是根節點是第0層,那麼Length返回的是第1層的元素個數,這裏是2。
Dimensions 返回的是"規則"列表的維數列表,這裏是:{2, 3, 2}
意思是樹形結構中,第0層節點均有2個分支、第1層節點均有3個分支、第2層節點均有2個分支。
所謂「規則」列表的意思是,每一個節點上的分支數是要同樣的。
那若是不同會咋樣呢?
Dimensions[{{a, b, c}, {d, e}, {f}}]
得:{3}
根節點下,有3個分支,OK,得3。而後第1層節點下分支數不一樣了,Dimensions就中止工做(輸出),歇菜。
{{a, b, c}, {d, e}, {f}} // TreeForm
TreeForm很好用啊。。樹形結構很好用。。
----------------------------------------------------
三、對錶中元素的處理
處理?無非取得一些、添加一些、替換一些。還有一些是你想不到的,咱們一一來舉例說明。
---------------------------
Position[{a,7,a,2,4,4},a]
得:{{1}, {3}}
列表中的元素位置,是從1開始的,不是從0開始。
爲啥不返回:{{1,3}} ?
請看:
Position[{{1,f,3},{4,5,f}},f]
得:{{1, 2}, {2, 3}}。f在第1行的第2列,和在第2行的第3列。
{1,2}這種形式,已經有人用過了。。
還有一個要注意一下:列表函數的返回值,常常以列表形式出現。由於列表函數常常嵌套使用,表中有表。。
---------------------------
Part[{1,2,f,4},3]
{1,2,f,4}[[3]]
抽取表中的第3個元素,這兩種方式抽取,結果是同樣的。
也就是說[[]]只是表面,在MMA內部,仍是Part...還記得吧?MMA內部結構,都是函數(表達式)。
Part還有兩個功能:
Part[{{1, f, 3}, {4, 5, f}}, 1, 2]
得:f
取得數組中的第1行、第2列元素。
在MMA中,數組常常指比較規則的表(用樹形結構看,分支數相同),與C、Pascal中的數組概念不一樣的。
這個程序看起來,有點不太明顯,用下面的是同樣效果:
{{1, f, 3}, {4, 5, f}}[[1, 2]]
這樣看起來,要好理解不少。
Part[{{1, f, 3}, {4, 5, f}}, {1, 2}]
{{1, f, 3}, {4, 5, f}}[[{1, 2}]]
這兩句是等效的,猜猜看,獲得什麼結果?
既然如此,來個更復雜的:
{{1, f, 3}, {4, 5, f}}[[{1, 2}]][[{1, 2}]][[{1, 2}]][[1,2]]
這就是傳說中的語法糖。
用好了,代碼可閱讀性急劇提升。
用差了,代碼就不知所云了,變成惡搞了(好比上面這個)。
---------------------------
Take,能夠前取、後取、連續取
Take[{1,2,3},1]
Take[{1,2,3},-1]
Take[{1,2,3},{1,2}]
Take[{1,2,3},{-3,-1}]
Take[{1,2,3},{-3,2}]
Drop,能夠前刪、後刪、連續刪
Drop[{1,2,3},1]
Drop[{1,2,3},-1]
Drop[{1,2,3},{1,2}]
Drop[{1,2,3},{-3,-1}]
Drop[{1,2,3},{-3,2}]
---------------------------
Delete,刪除指定位置上的元素。
Delete[{1, 2, 3, 4, 5}, {{2}, {3}}]
得:{1, 4, 5}
Delete[{{1, f, 3}, {4, 5, f}},{1, 2}]
得:{{1, 3}, {4, 5, f}}
Delete要刪除的,都必須特別指定位置。若是想連續刪,用Drop。
---------------------------
First/Last/Rest,不言自明:
First[{1,2,3}]
Last[{1,2,3}]
Rest[{1,2,3}]
注意兩點:First和Last返回的不是表,是表中的元素。
而Rest返回的是表。
---------------------------
Select/Reverse/Sort,又是不言自明的。
Select根據特定條件抽取表中元素。特定條件就是謂詞,返回布林值,即不是真就是假。
Reverse是反轉表。
Sort是排序。
Select[{1,2,3,4},EvenQ]
Reverse[{1,2,3,4}]
Sort[{2,1,4,3}]
與EvenQ相似的有不少,能夠顧名思義:IntegerQ OddQ TrueQ PrimeQ ...
Sort默認是排出升序。但也能夠指定爲降序:
Sort[{4, 1, 3, 2, 2}, Greater]
在Greater位置,也能夠放上排序函數。
---------------------------
RotateLeft/RotateRight
這兩個函數,能夠把表當作是能夠轉動的輪子。
能夠指定轉動步長。
RotateLeft[{1,2,3,4},1]
RotateRight[{1,2,3,4},2]
---------------------------
Flatten
能夠把嵌套表,展平(flatten,或者翻譯成壓平更容易理解?)到各類不一樣的層次。
說到層次,又要用樹形結構。
lis = {{{1, 2}, {3, 4}, {5, 6}}, {{a, b}, {c, d}, {e, f}}};
lis // TreeForm
Flatten[lis, 1]
% // TreeForm
Flatten[lis, 2]
% // TreeForm
lis =.;
觀察輸出結果,很容易理解。感性理解,就是一層一層剝皮,即把{}一層一層從外到內剝離。
那麼不指定層次會如何?指定層次越大了會如何?能夠玩一下:
lis = {{{1, 2}, {3, 4}, {5, 6}}, {{a, b}, {c, d}, {e, f}}};
lis // TreeForm
Flatten[lis]
% // TreeForm
Flatten[lis, 200]
% // TreeForm
lis =.;
答案揭曉:不指定層次,是一剝到底。層數過大時,也同樣是一剝到底。
---------------------------
Partition
功能十分強大而複雜,這裏只介紹經常使用的兩個功能。
Partition[list,n]
將列表 list 分割成不重疊的具備長度 n 的子列表
Partition[Range[10],2]
Partition[list,n,d]
生成偏移量爲 d 的子列表
Partition[Range[10],2,5]
---------------------------
Transpose
轉置表中的前兩層。
lis = {{a, b, c, d}, {1, 2, 3, 4}};
lis // Transpose
lis =.;
得:{{a, 1}, {b, 2}, {c, 3}, {d, 4}}
從表的角度看,是內部穿線同樣。
從二維數組或者矩陣的角度看,如同行列轉換:
lis = {{a, b, c, d}, {1, 2, 3, 4}};
lis // MatrixForm
Transpose[lis] // MatrixForm
lis // TableForm
Transpose[lis] // TableForm
lis =.;
---------------------------
Append/Prepend
添加元素到表的前面、後面。
Append[{1,2,3},4]
Prepend[{1,2,3},4]
---------------------------
Insert/ReplacePart
Insert[list,elem,n]
在 list 中的位置 n 上插入 elem。 若是 n 爲負,位置從結尾計算。
Insert[{1, 2, 3}, a, 2]
Insert[{1, 2, 3}, b, -2]
能夠觀察到,當n爲正數時,插入到指定位置前面。當n爲負數時,插入到指定位置的後面。
ReplacePart[expr,i->new]
產生一個表達式,其中用 new 替換 expr 的第 i\[Null] 個元素.
ReplacePart[{1, 2, 3}, a, 2]
第2個位置的元素(2),被a替換掉了。
這是MMA較老版本(好比2.0版)的寫法,如今也是支持的。較新版本(好比9.0版本)通常寫成這樣:
ReplacePart[{1, 2, 3}, 2 -> a]
效果是同樣的。但新版本的寫法能夠擴充:
ReplacePart[{1, 2, 3}, {1 -> a, 3 -> c}]
這裏第一次碰到轉換符號:->,之後還會詳細說的。
----------------------------------------------------
四、對多個表的處理
Join / Union
Join[{1,2},{3,4},{5,6}]
Join將數個錶鏈接起來。另外,Join還能夠指定層數鏈接,這裏不舉例了。
Union[{6,6},{3,4},{1,1}]
Union鏈接數個表以後,還把重複元素去掉,而後再排序。這有點集合操做的味道了,取並集。
由於Union有去重排序功能,固然也能夠對一個表操做。但Union沒有指定層數的功能。
Complement / Intersection
Complement求第一個列表中不出如今後面任何一個列表中的元素
Complement[{a, b, c, d, e}, {a, b, c}]
得:{d, e}
判斷元素屬於集合A、而不屬於集合B。
(*
這裏彷佛缺乏一個屬於的判斷函數。
可使用Position函數與Length函數來作屬於函數。數組
——想多了,能夠F1這兩個函數:Element MemberQ
*)
MMA彷佛還缺乏一個取補集的函數。且慢,若是把Complement函數的兩個參數,看做表1與表2,
而後呢,把表1看做是全集,把表2看做是子集,那麼Complement返回的就是補集!
繼續來看Intersection函數。
Intersection[{1, 2, 1, 3}, {2, 1, 4}, {4, 1, 2, 3}]
得:{1, 2}
求交集。由於相似於集合運算,因此有去重排序功能。
若是用語法糖,直接寫成這樣,會更清楚:
{1, 2, 1, 3} \[Intersection] {2, 1, 4} \[Intersection] {4, 1, 2, 3}
----------------------------------------------------
五、高階函數
有一些內置函數,把其餘函數做爲本身的參數,咱們稱之爲:
高階函數(higher order function)。
其實就是函數嵌套啦。
---------------------------
Map
這個函數能夠將某一函數,做用於一個表的每一元素上。
Map[f, {3, 5}]
Map[Reverse, {{a, b}, {c, d}}]
Map[Sort, {{2, 6, 3}, {2, 4, 1}, {2, 3, 1, 4, 6}}]
MMA常常搞批發。這裏顯現出來了。
---------------------------
MapThread
多表元素,被分別組配到一塊兒做爲函數的參數。看例子:
MapThread[g, {{a, b, c}, {x, y, z}}]
MapThread[Power, {{2, 6, 3}, {5, 1, 2}}]
MapThread[List, {{5, 3, 2}, {6, 4, 9}}]
Transpose[ {{5, 3, 2}, {6, 4, 9}}]
最後兩行的功能是同樣的,Transpose的功能前面說過。
可是呢,Transpose只能有相似於行列轉換的功能,而MapThread功能就強多了。
另外,MapThread還有指定層數的功能。
---------------------------
Outer
將把一個函數做用於幾個表的元素的一切組合上。這是數學上外積(outer product)概念的通常化。
Outer[f, {a, b}, {2, 3, 4}]
Outer[List, {a, b}, {2, 3, 4}]
---------------------------
Apply
替換函數頭。
Apply[f, List[1, 2]]
Apply[Plus, List[1, 2]]
---------------------------
這裏多做點說明。
由於Map與Apply很是經常使用,因此有必要多瞭解一些。
Map[f, {3, 5}]
f /@ {3, 5}
Apply[f, List[1, 2]]
f @@ List[1, 2]
先後兩句的功能是徹底同樣的,
Map的語法糖是:
/@ 分別做用於
Apply的語法糖是:
@@ 僅替換函數頭
---------------------------
Map與Apply,都可以指定層數。
Map[f,expr] 或 f/@expr
將 f 應用到 expr 中第一層的每一個元素.
lis = {{{1, 2}, {3, 4}, {5, 6}}, {{a, b}, {c, d}, {e, f}}};
lis // TreeForm
Map[f, lis] (*做用於第1層*)
Map[f, lis, {2}] (*做用於第2層*)
Map[f, lis, 2] (*做用於第一、2層*)
lis =.;
Apply[f,expr]
或 f@@expr 用 f 替換 expr 的頭部.
lis = {{{1, 2}, {3, 4}, {5, 6}}, {{a, b}, {c, d}, {e, f}}};
lis // TreeForm
Apply[f, lis] (*做用於第0層*)
Apply[f, lis, {2}] (*做用於第2層*)
Apply[f, lis, 2] (*做用於第一、2層*)
lis =.;
---------------------------
附加說明函數的屬性。
MapThread[Plus,{{1,2,3},{1,2,3}}]
得:{2, 4, 6}
直接寫:
{1, 2, 3} + {1, 2, 3}
結果同樣。
既能夠被自動地轉到表參數的各個元素上,又能夠被自動地穿線於表參數的對應元素上的那些函數,咱們稱之爲具備可做用於表的元素的(Listable)屬性,即具備Listable屬性。許多MMA內置函數都具備這一屬性。
查看函數的屬性,用Attributes函數:
Attributes[Log]
Log[{2, 3, 4}, {4, 9, 16}]
由於Log函數有Listable屬性,因此有這種「穿線」功能。
---------------------------
Attributes[Plus]
得:{Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected}
Flat, 可結合的,即服從結合律。
Listable, 前面已經說明,有「穿線」功能。
NumericFunction, 顧名思義,用於數值計算的函數。
OneIdentity, 函數對同一參數的重複做用是無效的,Plus[Plus[a + b]] // FullForm
Orderless, 無順序的,即服從交換律。a+b與b+a同樣的。
Protected, 受保護的。用戶被禁止以任何顯著的方法來修改這個符號。有點其餘語言中保留字的味道。
----------------------------------------------------
六、函數對錶的重複做用
這些函數,對作迭代很是方便。
---------------------------
Nest / NestList
Nest[f, x, 5]
得:f[f[f[f[f[x]]]]]
函數做用於參數,返回值做爲參數,再被函數。。做用了5次。
NestList[f, x, 5]
得:{x, f[x], f[f[x]], f[f[f[x]]], f[f[f[f[x]]]], f[f[f[f[f[x]]]]]}
整個做用過程,給出了表。這樣全過程就很清楚了。
ff[x_] := x + 1;
NestList[ff, 0, 20]
---------------------------
Fold / FoldList
在每一次迭代中,即函數返回值做爲參數時,還另加表中的一個元素做爲第二個參數。
Fold[f, 0, {a, b, c, d}]
得:f[f[f[f[0, a], b], c], d]
FoldList[f, 0, {a, b, c, d}]
將整個過程當中,每一個步驟所得,均取出來,做爲表元素。
FoldList[Plus, 0, {a, b, c, d}]
FoldList[Plus, 0, {3, 5, 2, 4}]
FoldList[Plus, 0, Range[100]]
這個迭代過程很低效,只是爲了說明Fold的迭代過程。1+2+3+...+100,最後得5050
---------------------------
Inner
被當作是數學中點乘運算(Dot函數)的推廣。
Dot (.)
a.b.c 或 Dot[a,b,c]
給出向量、矩陣和張量的乘積,即點乘運算。
{a, b, c} . {x, y, z}
Inner[f, {a, b, c}, {d, e, f}, g]
得:g[f[a, d], f[b, e], f[c, f]]
f起到「穿線」組合參數的功能。而g起到最後的結合功能。
Inner[Times, {a, b, c}, {d, e, f}, Plus]
得:a d + b e + c f
Inner[List, {a, b, c}, {d, e, f}, Plus]
先是List起做用,產生三組表。而後是Plus起做用,用了「穿線」加法,最後得:
{a + b + c, d + e + f}
----------------------------------------------------
七、字符串和字符
字符串,在MMA中,是atom,最基本的數據類型。相似於一個值,不,就是一個值。
咱們說,在MMA中,一切都是表達式。除了函數,就是atom。
字符串不是函數、更不是字符數組,是atom。
1 // FullForm
"test" // FullForm
"test" // InputForm
Length["mathematica"]
---------------------------
StringLength...
字符串很特殊啊、不是這個不是那個,更不是表。因此表操做函數,不能直接用於字符串。
壞消息啊。
不過,好消息是:通常的表操做函數,前面加上String,就能夠用了:
StringLength["Mathematica"]
StringReverse["abcdefg"]
StringTake["abcde", 3]
StringDrop["ABCDE", -1]
StringPosition["abcde", "bc"]
...
能夠看到,從原理上,把字符串做爲字符列表來處理了。。
從學習上來講,咱們沒必要從頭至尾再學習一遍串操做函數了,由於與表操做函數太像了。。
一眨眼間,大部分串操做函數就理解了。
接下來,來幾個針對串操做的固定有函數。
---------------------------
ToCharacterCode/ FromCharacterCode
ToCharacterCode["mathematica"]
% - 32
FromCharacterCode[%]
第一句,轉化字符爲ASC碼。
第二句,上句輸出表中每一個元素減去32。
第三句,上句輸出表中每一個元素,轉化爲字符。
能夠看到,小寫都變成大寫了。
由於字符與ASC碼之間,能夠輕鬆轉化,那字符操做,就沒有問題了。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
祕密就在於:
由於MMA中任何事物,都具備表達式這一共同結構,因此在表操做中學到的大部份內置函數,也能夠用來對任何表達式(atom除外)操做。
清楚了吧?不少表操做函數,不是表專用的,其餘表達式上均可以用。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
雖然這章有點長,但咱們能夠說,最經常使用的MMA函數,咱們都掌握了。
MMA學習曲線上的重頭戲,就這麼愉快地上演完畢。
數據結構
++++++++++++++++++++++++++++++++less
擴展閱讀:木有。若是有時間,把經常使用表操做函數拼寫幾遍,熟練一下函數功能。函數
這裏有個mathematica 經常使用命令大全,按函數功能進行劃分,有時候能夠查閱。學習
Top
atom