跳到主要內容

RUBY,大寫數字轉小寫數字,國字數字轉阿拉伯數字

RUBY,大寫數字轉小寫數字,國字數字轉阿拉伯數字

今天,我在處理中文地址的時候,發現有人的門牌號碼填國字,譬如中正路四三號,也有人會填中正路43號,當然沒人是填中正路肆參號,反正程式邏輯是一樣的。(本方法忽略四十三->43這種格式,若有必要,請自行寫程式判定京兆億萬千百十出現的位置,是否合理,然後再進行轉換)

一般想到的就是把字串裡面每個字遍尋一遍,然後寫個switch,對出現的字元進行轉換,譬如:

// psudo code
for each character in string
    switch(character)
    case: '一'
        convert_to(1)
    case: '二'
        convert_to(2)
        .
        .
        .
    case: '九'
        convert_to(9)
    end
end

但其實你使用的是Ruby語言的話,其實Ruby語言有提供一個很簡潔的方法string.tr(from_str, to_str)

使用的方式是這樣子的,提供兩個字串,兩個字串相對應的位置會互相轉換,譬如提供兩個字串:

#輸入字串1
'abc'
#輸入字串2
'123'

則會將a變為1, b變為2, c變為3,舉個實際例子:

"xx_abc_xx".tr('abc', '123')
# 輸出 "xx_123_xx"

"xx_ccc_xx".tr('abc', '123')
# 輸出 "xx_333_xx", '1'跟'2'都沒出現?因為呼叫tr的字串裡面也沒有'a'跟'b'呀~

"cba".tr('abc', '123')
# 輸出 "321", 為什麼反過來?因為呼叫tr的字串是'cba'呀~(a變為1, b變為2, c變為3)

上面的例子,是比較快速簡易的應用,兩個輸入的字串長度一樣,對於呼叫tr方法的字串,就會將內容替換掉。那如果要傳入兩個字串不一樣長,譬如第一二個比較長,那多出來的部分則不會用到,譬如:

"abc".tr('ab', '123')
# 輸出"12c", 第二個引數中,那個'3'則不會用到

如果是第一個字串比較長,譬如:

"abc".tr('abc', '12')
# 輸出"122", 第一個引數比第二個引數的長度還要長,則第二個引數比較長沒得對應的部分,直接用第二個引數中,最後一個字元替換

#同理
"abcdefghijk".tr('abcdefg', '12')
# 輸出"1222222hijk"

所以我們將大小寫國字數字轉阿拉伯數字,可以全部用列舉的方舉出來,讓他們一一對應

chinese = "零一二三四五六七八九"
arabic = "0123456789"

"一三五七九".tr(chinese, arabic)
# 輸出 "13579"

# 反過來,也可以用阿拉伯數字轉國字
"98765".tr(arabic, chinese)
#輸出 "九八七六五"

#多個大寫數字
big_chinese = "零壹贰叁肆伍陆柒捌玖"
"壹贰叁肆伍".tr(big_chinese, chinese)
# 輸出"一二三四五"

但這邊有個簡易的寫法,參考Ruby的正規表示式(可以在這個網頁做測試)

輸入引入的部分,如果正規表示式中,使用中括號的用法,例如:

[abc]  # 表示任何abc
[^abc] # 表示任何非abc,注意'^'符號放在中括號內,代表'非',而不是代表開頭字元
[1-9] # 表示任何1到9之間的字元

所以我們數字轉換的例子也可以寫成

chinese = "零一二三四五六七八九"
"一三五七九".tr(chinese, '0-9')
# 輸出 "13579"

就可以直接用'0-9'代表所有的阿拉伯數字,那麼是否也可以用'零-九'來代表所有的國字數字呢?

不行的,因為國字的排序並不像英文字元一樣的排法,你可以這樣測試看看

('零'..'九').each{|c| puts c}
# 沒有印出任何字元

('一'..'九').each{|c| puts c}
#印出 一 丁 丂 七 丄 丅 丆 ... 九

可見國字是用筆劃排序的,所以無法使用'零-九'來代表數字,得一一列舉出來。

所以關於門牌號碼,就可以這樣子處理了,全部轉為阿拉伯數字

address = '中正路四三號'
chinese = "零一二三四五六七八九"

address.tr(chinese, '0-9')
輸出"中正路43號"

同理,也可以玩玩英文大小寫轉換

# 小寫轉大寫,一般寫法
'hello world'.upcase # => "HELLO WORLD"

# 使用tr, 多此一舉一下
'hello world'.tr('a-z', 'A-Z') # => "HELLO WORLD"

留言

這個網誌中的熱門文章

HTML, CSS, 相對視窗或螢幕的高度與寬度

在 w3school.com 網站, CSS Units 有各種與寬度的表示法 以我使用的頻率來排序: px: 使用螢幕幾個像素(但是還要考慮Retina螢幕像素是一般螢幕像素的兩倍) %: 相對父層的大小比例 vh, vw: 相對於瀏覽器展示網頁區域的大小(不是整個瀏覽器的大小,沒包含瀏覽器的工具列,只有展示網頁的區域) vmin: vh, vw取最小值(另外還有vmax則是取最大值,但是目前IE跟safari不支援) px 與 % 很常用, vh , vw 與 vmin 是CSS3的新產物,表示相對瀏覽器展示頁面的大小 相對視窗大小 這邊先說明, vh , vw 與 vmin 只包含網頁顯示區域的長寬,不包含瀏覽器的工具列 先從dom的最根本講起好了,一份HTML文件,根是 <html></html> (雖然沒有嚴格規定,不寫也能顯示),然後這個根的父元件就是瀏覽器的網頁頁面顯示區 因此,如果對 <html></html> 宣告大小是 100% 就跟宣告 100vh 一樣,因為都是指瀏覽器的網頁頁面顯示區大小 這個範例是將html設定為100vh <html style="height: 100vh"> <head> <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script> <script type="text/javascript"> console.log($('html').height()); </script> </head> </html> 這個範例是將html設定為100% <html style="height: 100%"> <head> <script src="https://code.jquery.com/jque...

陣列洗牌程式(shuffle array)

陣列如何把它的順序打亂,作出類似洗牌的效果,我一直都很頭痛,搞得非常的複雜。至從用了Ruby,Array物件包含 shuffle 方法之後,我就沒思考過陣列洗牌的問題了,反正Ruby幫我處理得好好的。 Ruby # 52張牌的牌堆 poker = (1..52).to_a # => [1, 2, 3, ... , 52] # 洗牌打亂 shuffled = poker.shuffle # => [22, 32, 12, ... # 也可以直接打亂原來的陣列 poker.shuffle! # => [39, 47, 3, ... Javascript Javascript我就頭痛了,我得自己寫洗牌的方法。我在網路上找到了這個演算法,仔細看了之後,才知道原來洗牌可以這麼簡單: // 原本for迴圈是一行程式,太難理解,這邊改寫成多行 function shuffle(o){ for(var j, x, i = o.length; i;){ j = Math.floor(Math.random() * i); // javascript的array是0-base // 所以迴圈第一次進入,--i後表示陣列最後一個位置。 x = o[--i]; o[i] = o[j]; o[j] = x; // 以上三行代表以x為temp, o[i], o[j]做交換 } return o; //回傳陣列,我一開始也看錯看成回傳0 }; 變數說明 引數o: 將被洗牌的陣列 for迴圈內 i : 將會從陣列的最後一個位置,慢慢往前移到第一個位置(但移到第一個位置時for迴圈不執行,因為Javascript的數值0也代表false,會離開迴圈。0代表flase這點跟Ruby不一樣) j : 將會被亂數選擇,選到要被交換的位置 x : 用來暫存o[i]的數值,幫助o[i]與o[j]做數值交換 就這樣從最後一個位置開始,依次往前隨機挑選一個位置與它交換(可能挑到自己,表示不交換),來達到洗牌的效果,陣列多大,就執行幾次,時間複雜度 O(n) ,...

安裝zsh + oh-my-zsh 出現 /usr/bin/env: zsh: 沒有此一檔案或目錄 (/usr/bin/env: zsh -: No such file or directory)

zsh 跟 oh-my-zsh 安裝完,可能會出現類似下面錯誤訊息,雖然他沒任何影響,不過我總覺得怪怪的 # 中文系統 /usr/bin/env: zsh: 沒有此一檔案或目錄 # 英文系統 /usr/bin/env: zsh -: No such file or directory 通常會出現這類的訊息,都是指令找不到。 這邊指zsh這個指令找不到,試試看輸入 which zsh 看看是不是沒有把zsh這個加到 $PATH 裡面,沒有的話加入就好了。 如果加入了一樣找不到,我trace了一下zsh的執行過程,通常都是跟 oh-my-zsh 的安裝順序錯了的時候才會發生。 這時編輯家目錄底下檔案 vim ~/.zshrc ,會看到 # 他先執行了oh-my-zsh.sh source $ZSH/oh-my-zsh.sh # 然而oh-my-zsh.sh已經在使用zsh這個指令了 # 這裡才把宣告路徑,所以當然zsh指令找不到 export PATH="/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin:/bin:/root/bin:/usr/local/bin" 這時就把它們兩個對調一下就好了 # 像這樣把 export PATH 放到 source $ZSH/oh-my-zsh.sh 上面 export PATH="/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin:/bin:/root/bin:/usr/local/bin" source $ZSH/oh-my-zsh.sh # 這樣oh-my-zsh.sh裡面就可以用zsh指令了 存檔後,登出再進來,他就可以正常使用zsh指令,不再出現這種錯誤訊息了