# Mathematica/列表

## 列表的內容

``````In[]:= Clear[x];
List[Sin[x],Cos[x],Tan[x]]
Out[]= {Sin[x],Cos[x],Tan[x]}```
```

## 列表的產生

### 手動產生列表

``````In[]:= Clear[testlist,a,b,c,d,e];
testlist={a,b,c,d,e}
Clear[testlist];
Out[]= {a,b,c,d,e}```
```

### 用Range產生等距離數字列表

``````In[]:= Range[5]
Range[2,10]
Range[2,11,3]
Range[0,1,0.1]
Out[]= {1,2,3,4,5}
Out[]= {2,3,4,5,6,7,8,9,10}
Out[]= {2,5,8,11}
Out[]= {0.,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.}```
```

### 用Table產生列表

``````In[]:= Table[1,{i,1,10}]
Table[i^2,{i,1,10}]
Table[i*j,{i,1,3},{j,1,3}]
Table[i+j,{i,1,4},{j,1,i}]
Table[i+j+k,{i,1,2},{j,1,3},{k,1,3}]
Table[Sin[i],{i,1,10}]
Out[]= {1,1,1,1,1,1,1,1,1,1}
Out[]= {1,4,9,16,25,36,49,64,81,100}
Out[]= {{1,2,3},{2,4,6},{3,6,9}}
Out[]= {{2},{3,4},{4,5,6},{5,6,7,8}}
Out[]= {{{3,4,5},{4,5,6},{5,6,7}},{{4,5,6},{5,6,7},{6,7,8}}}
Out[]= {Sin[1],Sin[2],Sin[3],Sin[4],Sin[5],Sin[6],Sin[7],Sin[8],Sin[9],Sin[10]}```
```

``````In[]:= Clear[i,x];
Table[x^i,{i,1,10}]
Out[]= {x,x^2,x^3,x^4,x^5,x^6,x^7,x^8,x^9,x^10}```
```

``````In[]:= Clear[i,j,x];
Table[x^{i+j},{i,1,3},{j,1,3}]
Out[]= {{{x^2},{x^3},{x^4}},{{x^3},{x^4},{x^5}},{{x^4},{x^5},{x^6}}}```
```

``````In[]:= Clear[f,i];
f:=i^2;
Table[f,{i,5}]
Out[]= {1,4,9,16,25}```
```

``````In[]:= i
Out[]= i```
```

``````In[]:= Table[If[i>3,Return[],i],{i,10}]
Out[]= {1,2,3,Return[],Return[],Return[],Return[],Return[],Return[],Return[]}```
```

### 小議Range的普適性

``````In[]:= Range[10]^0
Range[10]^2
Out[]= {1,1,1,1,1,1,1,1,1,1}
Out[]= {1,4,9,16,25,36,49,64,81,100}```
```

```In[]:= (Range[3]*#)&/@Range[3] Out[]= {{1,2,3},{2,4,6},{3,6,9}} ``````In[]:= Range[#+1,2*#]&/@Range[4] Out[]= {{2},{3,4},{4,5,6},{5,6,7,8}} ``````In[]:= Nest[Partition[#,3,1]&,Range[3,8],2] Out[]= {{{3,4,5},{4,5,6},{5,6,7}},{{4,5,6},{5,6,7},{6,7,8}}} ``````In[]:= Map[Sin,Range[10]] Out[]= {Sin[1],Sin[2],Sin[3],Sin[4],Sin[5],Sin[6],Sin[7],Sin[8],Sin[9],Sin[10]} ```
``````In[]:= Clear[x];
x^Range[10]
Out[]= {x,x^2,x^3,x^4,x^5,x^6,x^7,x^8,x^9,x^10}```
```

### 在循環結構中產生列表

#### 用Append或者Prepend產生列表

``````In[]:= For[testlist={};i=1,i<=10,i++,testlist=Append[testlist,Sin[i]]];
testlist
Out[]= {Sin[1],Sin[2],Sin[3],Sin[4],Sin[5],Sin[6],Sin[7],Sin[8],Sin[9],Sin[10]}```
```

``````In[]:= Sin[Range[10]]
Out[]= {Sin[1],Sin[2],Sin[3],Sin[4],Sin[5],Sin[6],Sin[7],Sin[8],Sin[9],Sin[10]}```
```

#### 題外話：myTiming：一個計量運行時間的函數

``````Clear[myTiming];
myTiming[x_]:= Module[
{z = 0, y = 0, timelim = 0.1, p, q, iterlist = (Power[10, #]& /@ Range[0, 10]),
nm = If[ToExpression[StringTake[\$Version, 1]] < 6, 2, 1]
},
Catch[If[(z = Nest[First, Timing[(y++; Do[x, {#}]);], nm]) > timelim,
Throw[{z, y}]]& /@ iterlist] /. {p_, q_} :> p / iterlist[[q]]
];
Attributes[myTiming]={HoldAll};```
```

#### 效率陷阱：用Append構造列表

``````In[]:= myTiming[For[testlist={};i=1,i<1000,i++,testlist=Append[testlist,Sin[i]]];]
Out[]= 0.19```
```

``` ```

``````In[]:= myTiming[Sin[Range[1000]];]
Out[]= 0.0013```
```

```In[]:= myTiming[Table[Sin[i],{i,1000}];]
Out[]= 0.0023
```

## 列表的完全形式

``````In[]:= Clear[testlist,complextestlist];
testlist=Range[10]
complextestlist=Range/@Range[5]
Out[]= {1,2,3,4,5,6,7,8,9,10}
Out[]= {{1},{1,2},{1,2,3},{1,2,3,4},{1,2,3,4,5}}```
```

``````In[]:= FullForm[testlist]
Out[]//FullForm= List[1,2,3,4,5,6,7,8,9,10]
In[]:= FullForm[complextestlist]
Out[]//FullForm= List[List[1],List[1,2],List[1,2,3],List[1,2,3,4],List[1,2,3,4,5]]```
```

````Clear[testlist,complextestlist];`
```

## 使用列表和它們的零件

### 列表索引和用Part取出元素

#### 簡單列表

``````In[]:= Clear[testlist];
testlist=Range[1,20,3]
Out[]= {1,4,7,10,13,16,19}```
```

``````In[]:= testlist[[3]]
Out[]= 7```
```

``````In[]:= Part[testlist,3]
Out[]= 7```
```

``````In[]:= testlist[[{2,4,5}]]
Out[]= {4,10,13}```
```

``````In[]:= Part[testlist,{2,4,5}]
Out[]= {4,10,13}```
```

``````In[]:= testlist[[-1]]
Out[]= 19```
```

#### 關於嵌套列表

``````In[]:= complextestlist=Range[5*#,5*#+4]&/@Range[5]
Out[]= {{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24},{25,26,27,28,29}}```
```

```In[]:= complextestlist[[2]] Out[]= {10,11,12,13,14} ```
``````In[]:= complextestlist[[{1,4,5}]]
Out[]= {{5,6,7,8,9},{20,21,22,23,24},{25,26,27,28,29}}```
```

``````In[]:= complextestlist[[1,1]]
Out[]= 5```
```

``````In[]:= complextestlist[[{1,1}]]
Out[]= {{5,6,7,8,9},{5,6,7,8,9}}```
```

``````In[]:= complextestlist[[-1]]
complextestlist[[-1,-1]]
Out[]= {25,26,27,28,29}
Out[]= 29```
```

``` ```

````Clear[testlist,complextestlist];`
```

### Extract

```In[]:= testlist=Range[1,20,3]; complextestlist=Range[5*#,5*#+4]&/@Range[5] Out[]= {{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24},{25,26,27,28,29}} ``````In[]:= Extract[testlist,1] Extract[complextestlist,1] Extract[complextestlist,{1,2}] Out[]= 1 Out[]= {5,6,7,8,9} Out[]= 6 ```
``````In[]:= Extract[complextestlist,{{1,2},{3},{4,5}}]
Out[]= {6,{15,16,17,18,19},24}```
```

### Take和Drop

``````In[]:= testlist=Range[1,20,3]
complextestlist=Range[5*#,5*#+4]&/@Range[5]
Out[]= {1,4,7,10,13,16,19}
Out[]= {{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24},{25,26,27,28,29}}```
```

```In[]:= Take[testlist,3] Out[]= {1,4,7} ``````In[]:= Take[testlist,{2,4}] Out[]= {4,7,10} ``````In[]:= Take[testlist,-3] Out[]= {13,16,19} ``````In[]:= Take[testlist,{-4,-3}] Out[]= {10,13} ``````In[]:= Drop[testlist,3] Out[]= {10,13,16,19} ``````In[]:= Drop[testlist,{2,4}] Out[]= {1,13,16,19} ``````In[]:= Drop[testlist,-3] Out[]= {1,4,7,10} ```
``````In[]:= Drop[testlist,{-4,-3}]
Out[]= {1,4,7,16,19}```
```

Take和Drop也有一些擴展的功能，能夠自動地對於嵌套列表進行結構上的操作，比如從矩陣中抽取子矩陣。我們並不在這裡敘述，詳見Mathematica幫助文檔。

### First，Rest，Last 和Most

First[list]實際上等價於list[[1]],

Rest[list]等價於Drop[list,1],

Last[list]等價於list[[-1]],

Most[list]等價於Drop[list,-1]。

### Length

```In[]:= testlist=Range[1,20,3] complextestlist=Range[5*#,5*#+4]&/@Range[5] Out[]= {1,4,7,10,13,16,19} Out[]= {{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24},{25,26,27,28,29}} ```
``````In[]:= {Length[testlist],Length[complextestlist]}
Out[]= {7,5}```
```

``````In[]:= Table[Length[complextestlist[[i]]],{i,1,Length[complextestlist]}]
Out[]= {5,5,5,5,5}```
```

### 用Part修改列表元素

#### Part的簡單使用

``````In[]:= Clear[a];
testlist=Range[1,20,3]
complextestlist=Range[5*#,5*#+4]&/@Range[5]
Out[]= {1,4,7,10,13,16,19}
Out[]= {{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24},{25,26,27,28,29}}```
```

``````In[]:= testlist[[5]]=a;
testlist
Out[]= {1,4,7,10,a,16,19}```
```

``````In[]:= For[i=1,i<=Length[complextestlist],i++,complextestlist[[i,Random[Integer,{1,5}]]]=a];
complextestlist
Out[]= {{5,6,7,8,a},{10,11,a,13,14},{15,16,17,18,a},{20,21,a,23,24},{25,26,27,a,29}}```
```

``````In[]:= Range[10][[3]]=a
Set::setps: Range[10] in the part assignment is not a symbol. >>
Out[]= a```
```

#### 用Part高效修改大型結構

``````In[]:= Part[complextestlist,All,2]={b,c,d,e,f};
complextestlist
Out[]= {{5,b,7,8,a},{10,c,a,13,14},{15,d,17,18,a},{20,e,a,23,24},{25,f,27,a,29}}```
```

### ReplacePart

```In[]:= Clear[a]; testlist=Range[1,20,3] Out[]= {1,4,7,10,13,16,19} ```
``````In[]:= ReplacePart[testlist,a,5]
Out[]= {1,4,7,10,a,16,19}```
```

``````In[]:= testlist
Out[]= {1,4,7,10,13,16,19}```
```

``````In[]:= ReplacePart[Range[10],a,5]
Out[]= {1,2,3,4,a,6,7,8,9,10}```
```

ReplacePart可以一次性改變多個元素，即使這些元素在表達式不同的層上，例子： ``` ```

``````In[]:= ReplacePart[Range[10],a,{{2},{5},{8}}]
Out[]= {1,a,3,4,a,6,7,a,9,10}```
```

### Position

Position用來確定元素在列表（或者是更普遍的Mathematica表達式）中的位置。這些元素可以匹配一個已給的表達式，或者確切地說，通過模式。

#### Position的基本用法

``````In[]:= testlist=Range[1,20,3]
complextestlist=Range[5*#,5*#+4]&/@Range[5]
Out[]= {1,4,7,10,13,16,19}
Out[]= {{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24},{25,26,27,28,29}}```
```

``````In[]:= Position[testlist,4]
Out[]= {{2}}```
```

``````In[]:= Position[complextestlist,12]
Out[]= {{2,3}}```
```

Position能夠和Extract一起使用，因為它們使用一樣的位置描述方式： ``` ```

``````In[]:= Extract[complextestlist,Position[complextestlist,10]]
Out[]= {10}```
```

#### Position的瑣碎使用

``````In[]:= Map[Most,Position[complextestlist,10]]
Out[]= {{2}}```
```

Map的作用會在隨後得到闡述，現在關鍵的是它使得如果位置列表包含幾個位置，最後一個元素將會被扔掉。比如，我們定義另一個嵌套列表，這個列表中的一些元素會出現不止一次： ``` ```

``````In[]:= complextestlist1=Range/@Range[6]
Out[]= {{1},{1,2},{1,2,3},{1,2,3,4},{1,2,3,4,5},{1,2,3,4,5,6}}```
```

``````In[]:= plist=Position[complextestlist1,4]
Out[]= {{4,4},{5,4},{6,4}}```
```

``````In[]:= Extract[complextestlist1,plist]
Out[]= {4,4,4}```
```

``````In[]:= Map[Most,plist]
Out[]= {{4},{5},{6}}```
```

``````In[]:= Extract[complextestlist1,Map[Most,plist]]
Out[]= {{1,2,3,4},{1,2,3,4,5},{1,2,3,4,5,6}}```
```

#### 例子：取出含有已給元素的子列表

``````Clear[sublistsWithElement];
sublistsWithElement[main_List,elem_]:=Extract[main,Map[Most,Position[main,elem]]];```
```

``````In[]:= sublistsWithElement[complextestlist1,5]
Out[]= {{1,2,3,4,5},{1,2,3,4,5,6}}```
```

#### 更複雜的例子——具有奇數個奇數元素的子列表

``````In[]:= complextestlist1=Range/@Range[6]
Out[]= {{1},{1,2},{1,2,3},{1,2,3,4},{1,2,3,4,5},{1,2,3,4,5,6}}```
```

``````In[]:= step1list=Position[complextestlist1,_?OddQ]
Out[]= {{1,1},{2,1},{3,1},{3,3},{4,1},{4,3},{5,1},{5,3},{5,5},{6,1},{6,3},{6,5}}```
```

``````In[]:= step2list=Split[step1list,First[#1]==First[#2]&]
Out[]= {{{1,1}},{{2,1}},{{3,1},{3,3}},{{4,1},{4,3}},{{5,1},{5,3},{5,5}},{{6,1},{6,3},{6,5}}}```
```

``````In[]:= step3list=Map[First,step2list,{2}]
Out[]= {{1},{2},{3,3},{4,4},{5,5,5},{6,6,6}}```
```

``````In[]:= step4list=Cases[step3list,x_List/;OddQ[Length[x]]]
Out[]= {{1},{2},{5,5,5},{6,6,6}}```
```

``````In[]:= step5list=Union[Flatten[step4list]]
Out[]= {1,2,5,6}```
```

``````In[]:= complextestlist1[[step5list]]
Out[]= {{1},{1,2},{1,2,3,4,5},{1,2,3,4,5,6}}```
```

``````Clear[oddSublists];
oddSublists[x_List]:=Part[x,Union[Flatten[Cases[Map
[First,Split[Position[x,_?OddQ],First[#1]==First[#2]&],{2}],y_List/;OddQ[Length[y]]]]]]```
```

``````In[]:= oddSublists[complextestlist1]
Out[]= {{1},{1,2},{1,2,3,4,5},{1,2,3,4,5,6}}```
```

``````Clear[oddSublistsNew];
oddSublistsNew[x_List]:=Map[If[EvenQ[Count[#,_?OddQ]],#/.#->Sequence[],#]&,x];```
```

``````In[]:= oddSublistsNew[complextestlist1]
Out[]= {{1},{1,2},{1,2,3,4,5},{1,2,3,4,5,6}}```
```

``````Clear[oddSublistsProc];
oddSublistsProc[x_List]:=Module[
{pos={},ctr,i,j},For[i=1,i<=Length[x],i++,
For[j=1;ctr=0,j<=Length[x[[i]]],j++,If[OddQ[x[[i,j]]],ctr++];];
If[OddQ[ctr],AppendTo[pos,i]];];Return[x[[pos]]]
];```
```

``````In[]:= oddSublistsProc[complextestlist1]
Out[]= {{1},{1,2},{1,2,3,4,5},{1,2,3,4,5,6}}```
```

``````Clear[complextestlist1,step1list,step2list,step3list,step4list,
step5list,oddSublists,oddSublistsNew,oddSublistsProc];```
```

## 列表元素的添加和刪除

### Append，Prepend，AppendTo和PrependTo

```In[]:= Clear[a]; testlist=Range[5] Out[]= {1,2,3,4,5} ``````In[]:= Append[testlist,a] Out[]= {1,2,3,4,5,a} ``````In[]:= Prepend[testlist,a] Out[]= {a,1,2,3,4,5} ```
``````In[]:= testlist
Out[]= {1,2,3,4,5}```
```

``````In[]:= testlist=Append[testlist,a];
testlist
Out[]= {1,2,3,4,5,a}```
```

```In[]:= testlist=Range[5] Out[]= {1,2,3,4,5} ```
``````In[]:= AppendTo[testlist,a];
testlist
Out[]= {1,2,3,4,5,a}```
```

Prepend和PrependTo是完全類似的。同時，回憶起先前的討論，我們會懷疑AppendTo或者PrependTo作用在一個列表上，而這樣的作用方式不是被分配給任何變量（不是一種左值（L-value））是一個錯誤。然而我們是對的：[9] ``` ```

```In[]:= Append[Range[5],a] Out[]= {1,2,3,4,5,a} ```
``````In[]:= AppendTo[Range[5],a]
Set::write: Tag Range in Range[5] is Protected. >>
Out[]= {1,2,3,4,5,a}```
```

````Clear[testlist];`
```

### Insert和Delete

```In[]:= Clear[a]; testlist=Range[3,15,2] Out[]= {3,5,7,9,11,13,15} ``````In[]:= Delete[testlist,4] Out[]= {3,5,7,11,13,15} ```
``````In[]:= Insert[testlist,a,5]
Out[]= {3,5,7,9,a,11,13,15}```
```

``````In[]:= testlist
Out[]= {3,5,7,9,11,13,15}```
```

## 關於嵌套列表

### Partition

#### 一個簡單的例子

``` ```

```In[]:= testlist=Table[Sqrt[i],{i,1,10}] Out[]={1,Sqrt[2],Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7],2 Sqrt[2],3,Sqrt[10]} ``````In[]:= Partition[testlist,3] Out[]={{1,Sqrt[2],Sqrt[3]},{2,Sqrt[5],Sqrt[6]},{Sqrt[7],2 Sqrt[2],3}} ```
``````In[]:= Partition[testlist,7]
Out[]= {{1,Sqrt[2],Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7]}}```
```

``````In[]:= Partition[testlist,7,1]
Out[]= {{1,Sqrt[2],Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7]},
{Sqrt[2],Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7],2 Sqrt[2]},
{Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7],2 Sqrt[2],3},
{2,Sqrt[5],Sqrt[6],Sqrt[7],2 Sqrt[2],3,Sqrt[10]}}```
```

#### 實際運用的例子：列表的moving average的計算

``` ```

``````Clear[listAverage];
listAverage[x_List]:=Apply[Plus,x]/Length[x];```
```

``````Clear[neighborLists];
neighborLists[x_List,m_Integer]:=Partition[x,Length[x]-2*m,1];```
```

``````In[]:= neighborLists[testlist,1]
Out[]={{1,Sqrt[2],Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7],2 Sqrt[2]},
{Sqrt[2],Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7],2Sqrt[2],3},
{Sqrt[3],2,Sqrt[5],Sqrt[6],Sqrt[7],2 Sqrt[2],3,Sqrt[10]}}```
```

``````In[]:= listAverage[neighborLists[testlist,1]]
Out[]= {1/3 (1+Sqrt[2]+Sqrt[3]),1/3 (2+Sqrt[2]+Sqrt[3]),1/3 (2+Sqrt[3]+Sqrt[5]),1/3 (2+Sqrt[5]+Sqrt[6]),
1/3 (Sqrt[5]+Sqrt[6]+Sqrt[7]),1/3 (2 Sqrt[2]+Sqrt[6]+Sqrt[7]),1/3 (3+2 Sqrt[2]+Sqrt[7]),1/3 (3+2 Sqrt[2]+Sqrt[10])}```
```

``````Clear[movingAverage,neighborLists,listAverage];
neighborLists[x_List,m_Integer]:=Partition[x,Length[x]-2*m,1];listAverage[x_List]:=Apply[Plus,x]/Length[x];
movingAverage[x_List,m_Integer]:=listAverage[neighborLists[x,m]];```
```

``````In[]:= movingAverage[testlist,2]
Out[]= {1/5 (3+Sqrt[2]+Sqrt[3]+Sqrt[5]),1/5 (2+Sqrt[2]+Sqrt[3]+Sqrt[5]+Sqrt[6]),
1/5 (2+Sqrt[3]+Sqrt[5]+Sqrt[6]+Sqrt[7]),1/5 (2+2 Sqrt[2]+Sqrt[5]+Sqrt[6]+Sqrt[7]),
1/5 (3+2 Sqrt[2]+Sqrt[5]+Sqrt[6]+Sqrt[7]),1/5 (3+2Sqrt[2]+Sqrt[6]+Sqrt[7]+Sqrt[10])}```
```

``````Clear[movingAverage];
movingAverage[x_List,m_Integer]:=(Plus@@#)/Length[#]&@Partition[x,Length[x]-2*m,1];```
```

``````In[]:= movingAverage[testlist,2]
Out[]= {1/5 (3+Sqrt[2]+Sqrt[3]+Sqrt[5]),1/5 (2+Sqrt[2]+Sqrt[3]+Sqrt[5]+Sqrt[6]),
1/5 (2+Sqrt[3]+Sqrt[5]+Sqrt[6]+Sqrt[7]),1/5 (2+2 Sqrt[2]+Sqrt[5]+Sqrt[6]+Sqrt[7]),
1/5 (3+2 Sqrt[2]+Sqrt[5]+Sqrt[6]+Sqrt[7]),1/5 (3+2 Sqrt[2]+Sqrt[6]+Sqrt[7]+Sqrt[10])}```
```

``````movingAverageProc[x_List,m_Integer]:=Module[
{i,j,ln=Length[x],aver,sum},aver=Table[0,{ln-2*m}];For[i=m+1,i<=ln-                      m,i++,sum=0;
For[j=i-m,j<=i+m,j++,sum=sum+x[[j]]];aver[[i-m]]=sum/(2*m+1)];aver];```
```

``````In[]:= movingAverageProc[testlist,2]
Out[]= {1/5 (3+Sqrt[2]+Sqrt[3]+Sqrt[5]),1/5 (2+Sqrt[2]+Sqrt[3]+Sqrt[5]+Sqrt[6]),
1/5 (2+Sqrt[3]+Sqrt[5]+Sqrt[6]+Sqrt[7]),1/5 (2+2Sqrt[2]+Sqrt[5]+Sqrt[6]+Sqrt[7]),
1/5 (3+2 Sqrt[2]+Sqrt[5]+Sqrt[6]+Sqrt[7]),1/5 (3+2 Sqrt[2]+Sqrt[6]+Sqrt[7]+Sqrt[10])}```
```

```In[]:= Timing[movingAverage[Range[10000],10];] Out[]= {0.016,Null} ```
``````In[]:= Timing[movingAverageProc[Range[10000],10];]
Out[]= {1.172,Null}```
```

``` ma1[x_List,m_Integer]:=ListCorrelate[ConstantArray[1,m],x]/m ```

```ma2[x_List,ker_List]:=ListCorrelate[ker,x]/Total@ker ```

`ma3[x_List,m_Integer]:=Average[RotateRight[x,#]&/@Range[0,m-1]] [ [m;;] ]`

````Clear[testlist];`
```

### Transpose

#### 簡單例子：調換一個簡單列表

``` ```

``````In[]:= testlist=Table[i+j,{i,1,2},{j,1,3}]
Out[]= {{2,3,4},{3,4,5}}```
```

``````In[]:= Transpose[testlist]
Out[]= {{2,3},{3,4},{4,5}}```
```

#### 例子：調換一個列表的列表

``````In[]:= testlist=Table[{i,j},{i,1,2},{j,1,3}]
Out[]= {{{1,1},{1,2},{1,3}},{{2,1},{2,2},{2,3}}}```
```

``````In[]:= Transpose[testlist]
Out[]= {{{1,1},{2,1}},{{1,2},{2,2}},{{1,3},{2,3}}}```
```

#### 例子：成績和姓名結合

``````Clear[names,scores];
names={"Smith","Johnson","Peterson"};
scores={70,90,50};```
```

``````In[]:= Transpose[{names,scores}]
Out[]= {{Smith,70},{Johnson,90},{Peterson,50}}```
```

`Flatten````这个函数用来破坏嵌套列表的结构，因为它搬走所有内部的花括号并将任何复杂的嵌套列表转换成一个平坦的列表。 ````简单例子：压平一个嵌套列表```` ``````In[]:= teselist=Table[{i,j},{i,1,2},{j,1,3}] Out[]= {{{1,1},{1,2},{1,3}},{{2,1},{2,2},{2,3}}} ``````In[]:= Flatten[testlist] Out[]= {1,1,1,2,1,3,2,1,2,2,2,3} ````壓平列表的特定層````我們可以令Flatten更仁慈些和有選擇性的，通過命令它去破壞表達式的某個層。被破壞的層可以在Flatten的可選擇的第二個參數中給出。比如： ``````In[]:= Flatten[testlist,1] Out[]= {{1,1},{1,2},{1,3},{2,1},{2,2},{2,3}} ``````例子：一層層地壓平一個嵌套列表 另一個例子： ``````In[]:= testlist=Table[{i,j,k},{i,1,2},{j,1,2},{k,1,3}] Out[]= {{{{1,1,1},{1,1,2},{1,1,3}},{{1,2,1},{1,2,2},{1,2,3}}},{{{2,1,1},{2,1,2},{2,1,3}},{{2,2,1},{2,2,2},{2,2,3}}}} ``````In[]:= Flatten[testlist,1] Out[]= {{{1,1,1},{1,1,2},{1,1,3}},{{1,2,1},{1,2,2},{1,2,3}}, {{2,1,1},{2,1,2},{2,1,3}},{{2,2,1},{2,2,2},{2,2,3}}} ``````In[]:= Flatten[testlist,2] Out[]= {{1,1,1},{1,1,2},{1,1,3},{1,2,1},{1,2,2},{1,2,3},{2,1,1},{2,1,2},{2,1,3},{2,2,1},{2,2,2},{2,2,3}} ``````In[]:= Flatten[testlist,3] Out[]= {1,1,1,1,1,2,1,1,3,1,2,1,1,2,2,1,2,3,2,1,1,2,1,2,2,1,3,2,2,1,2,2,2,2,2,3} ``````實際上，會更頻繁地用Flatten[expr]來得到一個完全平坦的列表。或者用Flatten[expr,1]來去掉一些內部的花括號當我們只需要一些起媒介作用的步驟而不再做其他操作。 ````應用：計算的二次規範的任意秩張量（向量，矩陣等）````問題和解決方案 這裡我們會展示Flatten是怎樣戲劇性地簡化任意秩的張量的二次範數計算的用處。令人吃驚的是我們將不需要把張量的秩作為一個單獨的參數。所以，我麼將從這個代碼開始： ``````Clear[tensorNorm]; tensorNorm[x_List]:=Sqrt[Plus@@Flatten[x^2]]; ``````這裡說明了這個簡潔的代碼是解決問題的主要部分。 解剖代碼： 讓我們先用一個例子來說明它是怎麼工作的。這是我們的矩陣： ``````In[]:= testmatr=Table[i+j,{i,1,3},{j,1,3}] Out[]= {{2,3,4},{3,4,5},{4,5,6}} ``````範數就是對矩陣的所有元素的平方和開根號。首先，我們要利用一個事實：算數操作比如（raising to some power）能夠作用在整個列表上。因為它們能夠自動地貫穿整個列表（具有這種性質的函數說成是Listable）。因此，我們首先平方所有元素： ``````In[]:= testmatr^2 Out[]= {{4,9,16},{9,16,25},{16,25,36}} ``````既然我們並不關心元素確切的位置而只需要對它們求和，我們用Flatten來去掉內部的花括號： ``````In[]:= Flatten[testmatr^2] Out[]= {4,9,16,9,16,25,16,25,36} ``````現在我們有了所有的元素組成的列表了，而且我們已經看到這個可以靠Plus@@來建造： ``````In[]:= Plus@@Flatten[testmatr^2] Out[]= 156 ``````最後，我們還要開平方： ``````In[]:= Sqrt[Plus@@Flatten[testmatr^2]] Out[]= 2 Sqrt[39] ``````哈，我們得到函數代碼啦。我們看到函數很漂亮地作用具有任意秩的張量上而沒有作修改！沒有了Flatten是很難做到的，尤其是在像C語言的那些語言裡，我們會需要嵌套循環來完成。（在C語言裡，也是有一個叫做壓平數組的技巧，但是它存在於利用row-major order，而這個row-major order儲存在內存中並且 多維數組 雖然它能夠發揮作用，但那將是非法的如果你想嚴格遵照C語言的標準）。[10] ``````Clear[tensorNorm,testmatr]; ````應用:用Flatten（相當地）快地產生列表````就像我們曾經談到的，在效率方面，在循環中直接生成列表可能是最糟糕的方式。我們可以使用Flatten來對這個過程進行提速，這是可以考慮的。我們想生成一個從1到10的列表（最簡單的，當然，只要Range[10]就能完成），我們用接下來的方式來做： 步驟一：我們生成一個嵌套列表（這種列表在Mathematica中也叫做linked lists）： ``````In[]:= For[testlist={};i=1,i<=10,i++,testlist={testlist,i}]; testlist Out[]= {{{{{{{{{{{},1},2},3},4},5},6},7},8},9},10} ``````步驟二：我們使用Flatten： ``````In[]:= Flatten[testlist] Out[]= {1,2,3,4,5,6,7,8,9,10} ``````讓我們來用之前使用Append的方式來對比一下運行時間 ``````In[]:= For[testlist={};i=1,i<5000,i++,AppendTo[testlist,i]];//Timing Out[]= {0.25 Second,Null} ``````現在是我們的新方法： ``````In[]:= (For[testlist={};i=1,i<5000,i++,testlist={testlist,i}];Flatten[testlist];)//Timing Out[]= {0.016 Second,Null} ``````我們看到差距至少就在於命令的長度。即使這個方法本身並不是最有效率的，但是我們將會看到嵌套列表是怎樣被用來戲劇性地在某些問題中提高效率。 ``````Clear[testlist]; ````列表間的集合運算````經常會用到兩個或兩個以上列表的併集，交集和補集，也經常要去掉列表中的重複的元素。這些可以用內置函數Join，Intersection，Complement和Union來完成。 ````Join````函數Join把兩個或兩個以上的列表連接起來。格式是Join[list1,…,listn]，<list1,…,listn>是列表，不要求具有相同的深度和結構。如果列表包含相同的元素，這些相同的元素並沒有被刪除，也就是列表被連接起來，而在它們的內部結構中沒有更多的修改。例子： ``````Clear[a,b,c,d,e,f]; ``````In[]:= Join[{a,b,c},{d,e,f}] Out[]= {a,b,c,d,e,f} ``````In[]:= Join[{{a,b},{c,d}},{e,f}] Out[]= {{a,b},{c,d},e,f} ``````Join從左往右把列表連接在一起，沒有對列表進行任何排序和變換。 ````Intersection````函數Intersection找到兩個或兩個以上列表的共同元素，也就是說它將得到屬於所有列表的所有元素。格式是：Intersection[list1,…,listn]。例子： ``````In[]:= Clear[a,b,c,d,e,f]; Intersection[{a,b,c},{b,c,d,e}] Out[]= {b,c} ``````In[]:= Intersection[{a,b,c,d,e,f},{a,b,c},{c,d,e}] Out[]= {c} ``````In[]:= Intersection[{a,b,c},{d,e,f}] Out[]= {} ``````在最後的例子中我們得到一個空列表，因為兩個列表的交集是空集。 函數Intersection有一個選項SameTest，這個選項可以用來提供一個定製的「sameness」函數——即我們可以定義「same」的概念，與默認情況下是不同的。請看函數Union關於這個選項運用的例子。同時，有了這個選項，Intersection會變得很慢，比它單純的形式更慢。在附錄C中有詳細的描述。 ````Complement````函數Complement[listAll,list1,…listn]給出其他列表<list1,…listn>的併集在列表<listAll>中的補足元素。換句話說，它返回在列表<listAll>中的而不再任何一個列表<listk>的元素。而且Complement還對結果排序。例子： ``````In[]:= Complement[{a,b,c,d,e,f},{b,c,e}] Out[]= {a,d,f} ``````In[]:= Complement[{a,b,c,d,e,f},{b,c,e},{d,e,f}] Out[]= {a} ``````In[]:= Complement[{a,b,c,d,e,f},{b,c,e},{d,e,f},{a,b,c}] Out[]= {} ``````函數Complement，就像Intersection一樣也有選項SameTest。它允許我們定義關於「same」的觀念。所有的我對Intersection關於這個選項的註解，將在這本書裡應用。 ````和列表排序相關的函數````這裡我們討論非常和列表排序有關的有用的內置函數。函數Sort對列表進行排序。函數Union去除列表中的重複元素並且對結果排序。函數Split將列表分割為由相同的靠近的元素構成的子列表。對這三個函數都可以定義「sameness」的概念，而與默認的定義不同。下面，我們給出更多的細節和每個函數用法的例子。 ````Sort``基礎Sort````這個函數用來對列表進行排序。比如： ``````In[]:= Clear[a,b,c,d,e,f,g,t]; Sort[{a,d,e,b,g,t,f,d,a,b,f,c}] Out[]= {a,a,b,b,c,d,d,e,f,f,g,t} `````` ``````In[]:= Sort[{5,7,2,4,3,1}] Out[]= {1,2,3,4,5,7} ``````函數Sort可以對任意Mathematica表達式進行排序。由於疏忽（by default），Sort是依照詞典編撰對符號進行排序，按數字的升序進行或者依照列表的第一個元素。總之，這就是Mathematica中的標準排序順序，查詢Mathematica幫助文檔可以得到更多信息。 作為例子，我們對一個嵌套正數列表進行排序： ``````In[]:= nested=Table[Random[Integer,{1,15}],{5},{Random[Integer,{3,10}]}] Out[]= {{13,3,11,7},{15,15,14,11,15,14},{11,10,2},{11,12,9,11,1,4},{7,4,15,11,9}} ``````In[]:= Sort[nested] Out[]= {{11,10,2},{13,3,11,7},{7,4,15,11,9},{11,12,9,11,1,4},{15,15,14,11,15,14}} ``````我們看到排序是在按照子列表的第一個元素進行的。[11] ````按照用戶定義的排序函數進行排序````作為一個選項的第二個參數，Sort接受一個對比函數來替代默認函數。例子： ``````In[]:= Sort[{5,7,2,4,3,1},Greater] Out[]= {7,5,4,3,2,1} ``````我們可以按照子列表的長度來排序嵌套列表。首先定義一個排序函數： ``````Clear[sortFunction]; sortFunction[x_List,y_List]:=Length[x]<Length[y]; ``````然後我們來進行排序： ``````In[]:= Sort[nested,sortFunction] Out[]= {{11,10,2},{13,3,11,7},{7,4,15,11,9},{11,12,9,11,1,4},{15,15,14,11,15,14}} ````初識純函數````Mathematica提供一個途徑來構造和使用函數，而沒有給出這些函數的名稱或者單獨的定義，這些就叫做「純函數」（pure function）（在一些語言中也叫做 函數（lambda function））。我們將系統性地介紹它，但是現在我們只是為了理解上面的排序過程才提及純函數。 ``````In[]:= Sort[nested,Length[#1]<Length[#2]&] Out[]= {{11,10,2},{13,3,11,7},{7,4,15,11,9},{11,12,9,11,1,4},{15,15,14,11,15,14}} ``````任何可以返回True或者False的帶有兩個變量的函數都可以稱為排序函數。這是假定了給出True或者False依賴於那一個元素更「大」。 我必須提到人們使用Sort——定義了排序函數，會使得程序變慢，在附錄C中有詳細討論。 ````Ordering````該函數給出列表中元素按Sort順序排列的位置。它裡頭也可以有用戶定義的「純」形式——定義對比函數。它給出的信息比僅僅只有Sort的情況下更多，特別是結合Orderding和Part來排序列表。 列表： ``````In[]:= listtosort={a,d,e,b,g,t,f,d,a,b,f,c} Out[]= {a,d,e,b,g,t,f,d,a,b,f,c} ``````In[]:= Ordering[listtosort] Out[]= {1,9,4,10,12,2,8,3,7,11,5,6} ``````In[]:= listtosort[[Ordering[listtosort]]] Out[]= {a,a,b,b,c,d,d,e,f,f,g,t} ``````Ordering是一個很有用的函數，正是因為它給出的信息比僅僅只有Sort的情況下更多，而且和Sort本身具有一樣的效率。我們將會在第六章看到它的例子。 ````Union````函數Union格式是Union[list]返回的列表<list>所有不同元素的標準排序結果。 ````基礎Union````在它的基本形式里，Union把列表看成一個單獨的變量，在一個列表里返回已排序的唯一的元素。排序過程是在Mathematica默認排序函數下進行的（按照詞典編撰順序對符號表達式排序，對數字進行升序排列，依照列表的第一個元素等等）。例子： ``````In[]:= Union[{a,d,e,b,g,t,f,d,a,b,f,c}] Out[]= {a,b,c,d,e,f,g,t} ``````In[]:= testlist=Table[Random[Integer,{1,10}],{15}] Out[]= {9,7,4,3,1,1,8,2,2,10,7,4,9,1,4} ``````In[]:= Union[testlist] Out[]= {1,2,3,4,7,8,9,10} ``````Union對結果進行排序這一事實，本質上是和Union內部算法有關係的。如果元素沒有被排序，人們可以寫出一個傳統的union函數（我們會在5.2.6.2.5考慮一些這方面的實現），這個函數將會比內置函數Union慢。 ````帶有SameTest選項的Union````函數Union也有選項SameTest，它允許我們給出關於那些元素是「一樣」的定義。比如，我們認為只要兩個元素都是以3為模，那麼它們就是相同的： ``````In[]:= Union[testlist,SameTest->(Mod[#1-#2,3]==0&)] Out[]= {1,2,3} ``````帶有SameTest選項的Union函數會變得很慢，比不帶選項的Union慢的多。在附錄C有更多的討論。 ````Split````該函數用來把列表切成幾個子列表，以致於每個子列表的元素是相同的。它也可以接受「sameness」函數作為第二個可選的參數。它從頭到尾查看列表，並比較相鄰的元素，使用默認「sameness」函數（SameQ）或者是我們自己給出的「sameness」函數。每當相鄰的兩個元素不是一樣的，它就把已經是相同的元素放進一個列表里，然後再重新開始另一個子列表。 ````基礎Split````在基本形式中，Split把列表切成子列表，當只有一個參數時，使用SameQ來斷定元素的比較。這裡我們引入一個列表和它的排序結果： ``````In[]:= testlist=Table[Random[Integer,{1,15}],{20}] sorted=Sort[testlist] Out[]= {8,12,10,3,13,15,13,6,6,2,4,9,5,11,6,10,7,4,15,5} Out[]= {2,3,4,4,5,5,6,6,6,7,8,9,10,10,11,12,13,13,15,15} ``````因為一般在一個沒有被排序的列表里相鄰的元素是不同的，我們看到大多數子列表會含有一個單獨的元素; ``````In[]:= Split[testlist] Out[]= {{8},{12},{10},{3},{13},{15},{13},{6,6},{2},{4},{9},{5},{11},{6},{10},{7},{4},{15},{5}} ``````而一個已經排序的列表卻不是這樣： ``````In[]:= Split[sorted] Out[]= {{2},{3},{4,4},{5,5},{6,6,6},{7},{8},{9},{10,10},{11},{12},{13,13},{15,15}} ````帶有用戶定義的sameness函數的Split````我們現在可以定義兩個元素的「相同」，如果它們除以3有相同的餘數.然而，在使用Split把相同的元素放在一起之前，我們將會用不同的排序函數來排序列表。以致於當相鄰的兩個數除以3有相同的餘數時，就把它們放在一個已經排好序的列表里： ``````In[]:= mod3sorted=Sort[testlist,Mod[#1,3]<Mod[#2,3]&] Out[]= {15,6,9,6,6,15,3,12,4,7,10,4,13,13,10,5,11,5,2,8} ``````現在我們可以split這個列表了: ``````In[]:= Split[mod3sorted,Mod[#1,3]==Mod[#2,3]&] Out[]= {{15,6,9,6,6,15,3,12},{4,7,10,4,13,13,10},{5,11,5,2,8}} ``````Split是一個很有用的函數。因為它對列表執行一個簡單的掃視，而且只是比較相鄰的元素，具有線性的複雜性。再者，因為比較的次數等於列表的長度減一，和用戶定義的sameness函數（在函數Sort和Union那裡曾經討論過的）聯繫在一起時，它並不會碰到嚴重的性能上的障礙。 ````例子：run-length 編碼````Split的一個標準應用是run-length編碼。給出一個含有儘可能重複元素的列表，這個編碼由用一個像{{num1,freqk1},…}列表替換原來的列表。<freqk>給出<numk>出現的總次數。比如，以我們第一個例子的結果來說明：我們需要做的是把每一個子列表變成我們剛才所說的那種形式，可以這樣做： ``````Clear[runEncodeSplit]; runEncodeSplit[spl_List]:=Table[{spl[[i,1]],Length[spl[[i]]]},{i,Length[spl]}]; ``````Clear[runEncode]; runEncode[x_List]:=runEncodeSplit[Split[x]]; ``````檢驗： ``````In[]:= runEncode[sorted] Out[]= {{2,1},{3,1},{4,2},{5,2},{6,3},{7,1},{8,1},{9,1},{10,2},{11,1},{12,1},{13,2},{15,2}} ``````用函數式編程方法，我們可以去掉一個輔助函數runEncodeSplit： ``````Clear[runEncodeFP]; runEncodeFP[x_List]:=Map[{First[#],Length[#]}&,Split[x]]; ``````檢驗： ``````In[]:= runEncodeFP[testlist] Out[]= {{8,1},{12,1},{10,1},{3,1},{13,1},{15,1},{13,1},{6,2},{2,1},{4,1}, {9,1},{5,1},{11,1},{6,1},{10,1},{7,1},{4,1},{15,1},{5,1}}[12] ````例子：計算相同元素的頻率````作為另一個與Split有關的應用，我們將會結合Sort來實現一個可以計算列表中相同元素的頻率的函數。如果我們注意到我們剛才已經對原來的列表進行排序了，就是剛才的runEncode函數作用在一個已經排好序的列表上，這是極其容易的。 ``````Clear[frequencies]; frequencies[x_List]:=runEncode[Sort[x]]; ``````檢驗： ``````In[]:= frequencies[testlist] Out[]= {{2,1},{3,1},{4,2},{5,2},{6,3},{7,1},{8,1},{9,1},{10,2},{11,1},{12,1},{13,2},{15,2}} ``````實際上，本質上函數Frequencies被應用在附加的『Statistics『DataManipulation程序包中。 在很多其他情況下Split是很有用的，我們在接下來的章節中會給出更深入的例子。 Clear[testlist,sorted,mod3sorted,listDivide,frequencies,runEncodeSplit,runEncode,runEncodeFP]; ````小結：````本章我們介紹了列表——在Mathematica中資料結構最重要的磚塊。我們考慮了幾種列表操作比如生成列表，元素的取出，添加，替換和刪除，在列表中定位具有某種特性的元素，還有幾種特別的函數：在一個或集合列表上進行快速的結構性操作。還有一些關於排序列表的函數。一下內置函數得到詳細的討論：Range，Table，Part，Extract,Take,Drop,First,Rest,Most,Last,Position,Length,Append,Prepend,AppendTo,PrependTo,Partition,Transpose,Flatten,Join,Union,Intersection,Complement,Sort,Split。 有了這些函數武裝起來的我們，已經對解決各種各樣的問題有了很大的幫助。然而，我們需要serious program building另一個主要的組成部分——對Mathematica函數的理解：它們是什麼？怎麼定義它們？等等。這是下一章的主題。 ````註記```` ↑ 詳見Mathematica幫助文檔 ref/Depth ↑ 詳見Mathematica幫助文檔tutorial/ExpressionsAsTrees和ref/TreeForm ↑ 這裡譯得不好！原文：As these examples show,Table accepts one or more lists which indicate the iteration bounds,but we can fill the lists with some functions computed on the counters being iterated.In cases when we have more than one iterator, we create a nested list where the innermost iterators correspond to the outermost lists.As we see,the bounds of the more outermost iterators may depend on the variables of more innermost ones,in which case the lists will have sublists of different lengths. ↑ 原文在是用matrix的，但是考慮到在Mathematica中矩陣和列表還是有區別的，為了避免麻煩，故譯成列表。 ↑ 此處的clean不能光是理解為「簡潔」，還有「避免產生其他的麻煩」的意思。 ↑ 參見Mathematica幫助文檔tutorial/LevelsInExpressions中的「從樹結構的觀點看層次時，將樹的頂部看成第0層，一個表達式中的某一項所在的層次簡單地說就是它到頂層的距離.」準確些。 ↑ Ted Ersek's Mathematica Tricks - Verbeia.com ↑ 原文：Cases is the command used to find the list of all occurrences of some expression or pattern in a larger expression. ↑ 我不確定這樣翻譯是否正確，原文：The situation with Prepend and PrenpendTo is completely analogous.And also,recalling the previous discussions, we may suspect that the application of AppendTo of PrependTo to a list which is not assigned to any variable(not an L-value)is a mistake,and we will be correct: ↑ 這裡出現嚴重的問題!!!原文：in C,there is also a technique called flattening an array,which consists in exploiting the row-major order in which it is stored in memory and going through the multidimensional array with just a pointer to an integer(or whatever is the type of the smallest array . ↑ 原文最後一個程序結果是有問題的，譯者已修改。參見Mathematica幫助文檔ref/Sort，對於表達式排序，Sort 首先將較短表達式的放在前面，然後按深度優先的方式比較子集。 ↑ 這裡的testlist=Table[Random[Integer,{1,15}],{20}]，即testlist={8,12,10,3,13,15,13,6,6,2,4,9,5,11,6,10,7,4,15,5} ```