看板 Mathematica 關於我們 聯絡資訊
※ 引述《lambking (BB)》之銘言: : 想要寫一個function 去計算一個字串中某元素出現的次數 : 例如: : list={a,a,b,b,c,c,c,} ; : frequncycount[list] : output: : {{a,2},{b,2},{c,3}} : 請問有什麼方法能夠寫這個function ? : 謝謝 誠如chungyuandye所言 Mathematica內建的Tally指令是這個問題最好最快的解法 Tally甚至還能自訂"相同"元素的比對函數 但如果題目稍微變化一下呢? 像是想以連續相同元素個數對表示一串列 例如將{a,a,a,b,b,a,b,b,b,a,a}變成{{a,3},{b,2},{a,1},{b,3},{a,2}} 該怎麼計算呢? 當然可以用迴圈輕易地達成 不過這就無法發揮Mathematica的長處了 其實這類問題能夠非常直覺地以pattern跟rule解決 這也是Mathematica另一個強大之處 直接寫出原po問題的pattern/rule解法: {#, 1} & /@ list //. {head___, {x_, n_}, mid___, {x_, m_}, tail___} -> {head, mid, tail, {x, n + m}} 這麼直白的程式碼 相信許多人已經了解了其計算原理 一開始的 {#,1} & /@ list 利用純函數轉換原串列 例如{a,b,a,b,c,c,c}將變為{{a,1},{b,1},{a,1},{b,1},{c,1},{c,1},{c,1}} 這邊的 1 就是代表出現次數 接著後面的 //. 表示將持續替換後面的rule直到結果不再變化為止 如果寫的是 /. 那就表示僅替換一次 這裡先點到功能,稍後會說明為什麼要使用 //. 重點來了 後面的rule是這個程式碼的計算核心: {head___, {x_, n_}, mid___, {x_, m_}, tail___} -> {head, mid, tail, {x, n+m}} 簡要介紹一下: head___、mid___、tail___中的三連續底線 表示這些pattern可以匹配任意序列(sequence),並且可為空序列 如果只有2個連續底線也可匹配任意序列,但不包含空序列 至於單一底線,則是匹配任意表示式(expression) 例如其後的x_、n_、m_等 初學者在這邊只要簡單地想像為單一元素即可 仔細看的話會發現箭頭的左邊出現了兩個 x_ 這表示兩個pattern必須匹配相同的元素 而右邊只有出現一次 表示這個rule每作用一次就會減少一項 換句話說,它會合併相同的 x_ 項 並且將其出現次數相加 至於使用head___、mid___、tail___這三個pattern的原因 是為了表示這兩個x_之前、之後、之間可以存在任意序列,包含空序列 只要不斷地重複這個步驟 最後就能得到我們要的結果 這就是要使用 //. 的原因 介紹完這個解法之後,相信各位會覺得這真是太直接了 甚至可以說這個rule同時描述了問題以及解法 這是Mathematica pattern/rule好用之處 可惜的是,方便跟效率經常位於天平的兩端 這個方法的效率並無法與Tally相比 不過在串列不大的情況下,還是挺好用的 行文至此,忍不住要為各位出一道作業 如果將{x,n+m}換個位置: {head___, {x_, n_}, mid___, {x_, m_}, tail___} -> {head,{x,n+m}, mid, tail} 輸出結果是相同的(但順序可能不同) 但效率變得奇差無比 各位可以思考一下原因 回到先前拋出來的問題: 如何以連續相同元素個數對表示一串列 解法非常直覺: {#, 1} & /@ list //.{head___,{x_,n_},{x_,m_},tail___}-> {head, {x, n+m}, tail} 後話 pattern/rule不常被注意 但其實很好用 至於中文參考書籍可參考最近出版的Mathematica Cookbook -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.169.212.109 ※ 文章網址: https://www.ptt.cc/bbs/Mathematica/M.1422173233.A.00D.html
chungyuandye: {#[[1]],Length@#}&/@Split[list,(#1== #2)&] 01/25 17:02
LPH66: Pattern 其實可以說是 Mathematica 運算的核心 01/25 20:53
LPH66: 平常的函數定義及呼叫就是一個 pattern matching 的過程 01/25 20:53
LPH66: 所以 Pattern 用的好確實可以如虎添翼 XD 01/25 20:54
pig030: 太神了,感謝又學到新的用法了^^ 01/26 20:53
carelai: 對,這其實是Mathematica精妙之所在,Mathematica其實是 02/06 18:36
carelai: untyped functional language,和lisp一樣,請問lisp也有 02/06 18:37
carelai: 類似上面的pattern matching嗎? 02/06 18:38
carelai: 另外方便和效率是天平的兩端,不可兼得,贊這句話 02/06 18:41