Mathematica语法拾遗

Standard

这里是用来总结Mathematica中的一些语法、句式、函数等,不一定很有条理,只是作为记录而已。

以及,本页的代码是有语法高亮的,如果看不到,可能是js没有加载完全,稍等片刻即可。 ╯_╰

 

2014-07-07 Update 4 新增Inner/Outer及范例,新增一些关于列表操作的 One-liners 实例。
2014-06-23 Update 3 新增Sow/Reap以及Gather等价类操作,更新分配部分。
2014-06-22 Update 2 新增规则匹配部分。
2014-06-21 Update 1 新增列表操纵、分配操作、简写符号、四种表达式形式,以及新增In/Out显示。
2014-06-17 初稿 新增基本函数调用、简单函数式用法。

【基本语法——函数调用】

(*使用[]来调用函数*)
In[1]:= Prime[10001]
Out[1]= 104743
(*使用@语法来避免嵌套的"[...]",@右结合*)
In[2]:= Length@Union@IntegerDigits[1089]
Out[2]= 4
(*使用//语法来"格式化"某些内容*)
In[3]:= {{1,2},{3,4},{5,6}} // MatrixForm
Out[3]//MatrixForm= ...
(*或者用来作收尾工作,即直接写在后面*)
In[4]:= Union@IntegerDigits[1088] // Total
Out[4]= 9

 

【基本语法——四种表达式形式】

f[x, y] (* f[x, y]的标准形式 *)
f@x     (* f[x]   的前缀格式 *)
x//f    (* f[x]   的后缀格式 *)
x~f~y   (* f[x, y]的嵌入格式 *)
(* //的优先级非常低 *)
x + y // f (* 这等价于f[x + y] *)
(* @ 的优先级非常高 *)
f @ x + y  (* 这等价于f[x] + y *)

 

【初级语法——列表操作】

(*使用Append在列表后追加元素*)
In[5]:= Append[{1, 2, 3}, tail]
Out[5]= {1, 2, 3, tail}
(*使用Prepend在列表前追加元素*)
In[6]:= Prepend[{1, 2, 3}, head]
Out[6]= {head, 1, 2, 3}
(*对于二元函数,可以使用~符号进行简写*)
In[7]:= {1, 2, 3}~Append~tail
In[8]:= {1, 2, 3}~Prepend~head
In[9]:= {1, 2, 3}~Append~tail~Prepend~head
Out[7]= {1, 2, 3, tail}
Out[8]= {head, 1, 2, 3}
Out[9]= {head, 1, 2, 3, tail}
(*使用Join来合并两个列表*)
In[10]:= {a, b, c}~Join~{d, e, f}
Out[10]= {a, b, c, d, e, f}

【进阶语法——列表生成】

>> 等价类生成

(* 使用 Sow / Reap 来收集具有同样tag的数据 *)
(* 范例:将所有两位数按数位和进行分组 *)
In[11]:= Last@Reap[Sow[#, Plus @@ IntegerDigits@#] & /@ Range[10, 99]]
Out[11]= {{10}, {11, 20}, {12, 21, 30}, {13, 22, 31, 40}, 
          {14, 23, 32, 41, 50}, {15, 24, 33, 42, 51, 60},
          {16, 25, 34, 43, 52, 61, 70},
          {17, 26, 35, 44, 53, 62, 71, 80},
          {18, 27, 36, 45, 54, 63, 72, 81, 90},
          {19, 28, 37, 46, 55, 64, 73, 82, 91},
          {29, 38, 47, 56, 65, 74, 83, 92},
          {39, 48, 57, 66, 75, 84, 93}, 
          {49, 58, 67, 76, 85, 94}, {59, 68, 77, 86, 95},
          {69, 78, 87, 96}, {79, 88, 97}, {89, 98}, {99}}
(* 也可以使用 Gather 直接按等价类分组 *)
(* MapThread 用法见后 *)
In[12]:= Gather[Range[10, 99], 
          Equal @@ MapThread[Plus @@ IntegerDigits@# &, {{#1, #2}}] &]
Out[12]= << 与 Out[11] 相同 >>

>> 一些有关列表操作的例子 (One-liners)

(* 实例:求两个序列间的 Hamming 距离 *)
(* 法一:使用 MapThread 对两个列表间对应元素判断是否相等,最后统计 False 的个数 *)
hammingDistance[list1_, list2_] := 
  Count[MapThread[SameQ, {list1, list2}], False]

(* 法二:先转置,在用异或运算作用在列表第一层,不同的会得到1,相同的会得到0,最后求和 *)
hammingDistance2[list1_, list2_] := 
  Plus @@ BitXor @@@ Transpose@{list1, list2}
(* 以下为计算 01010 与 11100 间的 Hamming 距离 *)
In[15]:= hammingDistance[{0, 1, 0, 1, 0}, {1, 1, 1, 0, 0}]
Out[15]= 3

In[16]:= hammingDistance2[{0, 1, 0, 1, 0}, {1, 1, 1, 0, 0}]
Out[16]= 3
(* 从任意列表 list 中抽取 n 的元素(无重),相当于内置的 RandomSample *)
deal[list_, n_] := Complement[list, 
  Nest[Delete[#, Random[Integer, {1, Length[#]}]] &, list, n]]
(* 实例:n 个人排成一个圈,每隔一个人就处决掉其中一个,问最后剩下的那个的编号? *)
(* 采用的办法是将这些人排成一排,每次先将队伍第一个移到最后,再去掉第一个,循环n-1次 *)
survivor[list_] := Nest[Rest@RotateLeft@# &, list, Length[list] - 1]

(* 以下是 n = 10 的情形 *)
In[17]:= survivor[Range[10]]
Out[17]= {5}

 

【函数式编程基本思想】

函数式编程的思想是函数是第一等公民,可以作为变量或参数。例如内置的积分函数:

In[18]:= Integrate[Exp[I π x], {x, a, b}]
Out[18]=   

注意到被积函数本身也是一个函数。同时,Integrate 也可以求定积分。

In[19]:= Integrate[Exp[I π x], x]
Out[19]=   

 

 

【进阶语法——函数式】

(*对列表的每个元素作同样处理*)
Map[PrimeQ, Range[10]]
{False, True, True, False, True, False, True, False, False, False}
(*Map可以用/@简写*)
PrimeQ /@ Range[10]

【进阶语法——挑选元素】

(*使用Select选出符合条件的元素*)
(*下例为求100内的质数个数*)
Select[Range[100], PrimeQ] // Length

更多参见:寻找与模式匹配的表达式

 

【神奇的用法——分配】

(*将一系列操作作用于同一对象*)
Through[{f, g, h}@a]
{f[a], g[a], h[a]
(*将同一操作作用于列表的每一对象*)
Thread[f[{a, b, c}]]
{f[a], f[b], f[c]}
(*范例:将数学上的习惯写法 1<= a, b, c <=9 展开*)
(*使用Thread将列表对应分配*)
Thread[1 <= {a, b, c} <= 9]
{1 <= a <= 9, 1 <= b <= 9, 1 <= c <= 9}
(* MapThread 与 Thread 类似,不同之处是前者将参数将函数和变量分开表示 *)
MapThread[f, {{a, b, c}}]
{f[a], f[b], f[c]}
(* MapThread 可以做到将复合函数算子分配,而 Thread 做不到 *)
MapThread[f@g@# &, {{a, b, c}}]
{f[g[a]], f[g[b]], f[g[c]]}

【更复杂的分配】

(*一起使用Thread和Through达到类似分配律的效果*)
(*是Distribute的扩展版本*)
Thread /@ Through[{f, g}@{a, b}]
{{f[a], f[b]}, {g[a], g[b]}}
(*用Distribute实现分配律*)
Distribute[{f + g}.{a + b}]
a f + b f + a g + b g
(* 这实际上等价于 Distribute[Times[f + g, a + b], Plus], 将Times分配到Plus *)
(*Expand实施乘法对加法的分配*)
Expand[(a + b) (c + d)]
a c + b c + a d + b d
(*Distribute分配和式*)
(* f[a + b] => f[a] + f[b] *)
Distribute[f[a + b, c + d]]
f[a, c] + f[a, d] + f[b, c] + f[b, d]
(*Distribute分配指定的头部,此处为Times*)
(* g[a * b] => g[a] * g[b] *)
Distribute[g[a b c d], Times]
g[a] g[b] g[c] g[d]

 

【进阶用法——自动列表化】

(* 函数 Log 可自动线性作用于列表 *)
Log[{a, b, c}]
{Log[a], Log[b], Log[c]}
(* 但 Log 不能对方程进行线性作用 *)
Log[x == y]
(* 依旧返回 Log[x == y] *)
(* 可以用 Thread 使函数作用于方程两端 *)
Thread[%, Equal]
Log[x] == Log[y]

【外积与内积】

(* Outer[f, list1, list2] 给出list1和list2所有元素可能组合 *)
(* 并将f作用于这些结合,可以看成向量张量的推广 *)
Outer[f, {a, b}, {1, 2, 3}]
{{f[a, 1], f[a, 2], f[a, 3]}, {f[b, 1], f[b, 2], f[b, 3]}}
(* 范例:产生一个下三角Boolean矩阵  *)
Outer[Greater, {1, 2, 3}, {1, 2, 3}]
{{False, False, False}, {True, False, False}, {True, True, False}}
(* 范例:做一副扑克牌去打掼蛋吧~~ *)
cardDeck = Flatten[Outer[List, 
    {♣, ♦, ♥, ♠}, Join[Range[2, 10], {J, Q, K, A}]], 1]
{{♣, 2}, {♣, 3}, {♣, 4}, ... , {♦, 2}, {♦, 3}, ... ,{♠, K}, {♠, A}}
(* Inner 表示内积,f 作用到内部,g 作用在外部 *)
Inner[f, {a, b, c}, {d, e, f}, g]
g[f[a, d], f[b, e], f[c, f]]
Inner[Times, {a, b, c}, {d, e, f}, Plus]
a d + b e + c f
(* Inner 实际上是求内积的 Dot 函数的一种一般化形式 *)
Dot[{a, b, c}, {d, e, f}]
a d + b e + c f
(* 练习:用 Inner 写出表示散度的函数 Div[vecs, vars] *)
(* 其中 vecs = [e1, e2, ..., en], vars = [v1, v2, ..., vn] *)
(* 其散度形式为 ∂e1/∂v1 + ∂e2/∂v2 + ... + ∂en/∂vn *)

 

【进阶语法——模式匹配】

>> 一个结构的模式

(* f[x_]匹配形如f[anything]的表达式,使用 /. 进行模式替换*)
f[a] + f[b] + f[c + d] /. f[x_] -> x^2
a^2 + b^2 + (c + d)^2
(* 可以构造具有任何结构的模式 *)
f[{a, b}] + f[c] /. f[{x_, y_}] -> p[x + y]
f[c] + p[a + b]
(* Mathematica按结构相等来匹配表达式,而不是以数学上的相等来匹配 *)
(* 尽管1可以写成x^0, x也可形成x^1, 但因结构不等而没有匹配 *)
{1, x, x^2, x^3} /. x^n_ -> r[n]
{1, x, r[2], r[3]}
(* 尽管顺序不同,但Mathematica在匹配时会考虑交换律、结合律等性质 *)
f[a + b] + f[a + c] + f[b + d] /. f[a + x_] + f[c + y_] -> p[x, y]
f[b + d] + p[b, a]

>> 一类结构的模式

(* Cases[list, form] 给出与form匹配的list中的元素 *)
Cases[{3, 4, x, x^2, x^3}, x^n_ -> n]
{2, 3}
(* Count[list, form] 给出与form匹配的list中元素的个数 *)
Count[{3, 4, x, x^2, x^3}, x^n_ -> n]
2
(* Cases 可以指定层数 *)
(* 下例为在所有层(Infinity)中寻找整数(_Integer) *)
Cases[{3, 4, x, x^2, x^3}, _Integer, Infinity]
{3, 4, 2, 3}
(* Position[expr, form, lev, n] 给出与form匹配的前n项的位置 *)
(* 下例为给出任何层上出现的前两个x的幂次的位置 *)
Position[{4, 4 + x^a, x^b, 6 + x^5}, x^_, Infinity, 2]
{{2, 2}, {3}}
(* 给出精确位置后,用 ReplacePart 函数进行替换 *)
ReplacePart[{4, 4 + x^a, x^b, 6 + x^5}, new, %]
{4, 4 + new, new, 6 + x^5}
(* 寻找所有能写为两项和的方式 *)
ReplaceList[a + b + c, x_ + y_ -> g[x, y]]
{g[a, b + c], g[b, a + c], g[c, a + b], 
 g[a + b, c], g[a + c, b], g[b + c, a]}

>> 模式块命名、限制模式等

(未整理)

 

 

 

 

【一些奇怪的简写】

(*对一维列表,Tr与Total等价*)
Range[10] // Tr
(*对二维列表即矩阵,Thread可以替代Transpose*)
Thread@{{1, 2}, {3, 4}, {5, 6}}
(*当生成常数列表时,利用纯函数而不用ConstantArray[a, n]*)
Array[a&, n]
(*使用##指代纯函数的参数序列*)
+##& (*求其和*)
1##& (*求其积*)
(*科学计数法*)
2*^3
(*可以使用自增 / 自减运算符*)
While[i++ < 1,(*code*)]
While[++i < 1,(*code*)]
(*在压平二维列表时,可以使用Join替代Flatten@a*)
Join @@ a
(*StringJoin的简写形式*)
StringJoin@{"a", "b", "c"}
"" <> {"a", "b", "c"}

9

5

3

 

 

  • AlephAlpha

    好玩。

    • 在 codegolf 上久仰大名

  • Guest

    您好,我对您本文使用的 wolfram 语言代码高亮非常感兴趣……不知可否介绍或提供?万分感谢。