# 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} ```