跳到主要內容

發表文章

目前顯示的是 2月, 2014的文章

陣列洗牌程式(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) ,...

Rails 在CSS裡使用圖片

暴力法 反正最後都會被編譯在public下面,可以下 rake assets:precompile 指令,看看最後圖片被放到哪裡去了,通常都在 public/asset 底下,而網頁伺服器的根目錄是 public/ 所以你的css就直接把圖片定位在 /assets/ 底下,例如: .your_class { background-image:url('/assets/your_img.png'); } 非常不建議用這個方法,程式碼非常不靈活 內嵌Ruby法 在Rails裡面,你的檔案想要內嵌Ruby,只要把檔名結尾加上 .erb ,就可以最常見的就是 page.html.erb ,但可沒這麼簡單唷,就連CSS檔以可以內嵌Ruby,一樣把你的CSS加上 .erb ,譬如 style.css.erb ,這樣CSS內就可以使用Ruby了。 既然可以使用Ruby了,那就大膽的把Rails內建的Helper拿出來用吧, asset_path("img.jpg") ,就行了,例如: .your_class { background-image:url('<%= asset_path("your_img.png") %>'); } 這樣至少靈活多了,至少你不用擔心Rails編譯之後,會把你的圖檔放到Public的哪裡去,被改了什麼檔名。 SCSS法 Rails預設使用SCSS,你打開你的Gemfile就可以看到了,預設已經有 gem 'sass-rails' ,在Rails的CSS裡面取圖,我推薦這個方法,因為這個方法程式碼最簡潔: .your_class { background-image: image-url("your_img.jpg"); } 發生什麼事?沒錯使用SCSS的話, image-url("your_img.jpg"); 就行了, image-url 是Rails的Helper,可別跟CSS原生的 background-image:url(your_img.jpg); 給搞混囉 .your_class { /* 這個是Rails的Helper */ back...

Ruby,檔案定期備份

我最近把資料庫系統換成了SQLite,直接放到RamDisk去執行。今天想要寫支程式,可以定時檢查RamDisk,裡面的sqlite檔有沒有變動,有變動就備份到硬碟去。於是使用Ruby寫下了: FILE_TO_CHECK = ARGV[0] FILE_TO_SAVE = ARGV[1] if !File.exists?(FILE_TO_SAVE) `cp #{FILE_TO_CHECK} #{FILE_TO_SAVE}` exit end check_file = File.new FILE_TO_CHECK save_file = File.new FILE_TO_SAVE if check_file.mtime > save_file.mtime `cp #{FILE_TO_CHECK} #{FILE_TO_SAVE}` end 不錯,不錯,想說這樣這隻程式可以放到crontab去,將來有同樣要檢查的檔案就編輯在crontab裡: 0 * * * * ruby /check_file.rb sinkfile sourcefile 不過做到這邊,突然想到,安裝 rsync 不就行了,直接 0 * * * * rsync sinkfile sourcefile rsync就是檢查檔案有無更動,有更動的才會複製,而且它是這麼老牌又穩定的lib了,呵呵,沒關係,就當做是在練習使用vim編輯器

Ruby,Time.new(自定時間格式)

Ruby 製作Time物件時,必須遵守一定的格式,譬如 Time.new(2014, 2, 13, 16, 30, 30, "+08:00") #=> 2014-02-13 16:30:30 +0800 Time.new 裡頭接受的參數從年,月,日,時,分,秒,時區,沒填的就預設是0,全部都沒填,那就給系統當前時間。那問題如果我們得到的時間是一個字串呢?例如我們有一個時間字串: 2014-02-13 16:50:47 +0800 這串文字當參數傳到到 Time.new 裡面只會出現錯誤訊息,難道要開始做苦工先字串解析,在放到 Time.new 裡面嗎? Time.strptime 用到字串解析也就太辛苦了,Ruby 的Time class提供一個strptime方法,可以直接定義time format, require 'time' 之後就可以使用了直接舉個例子: require 'time' t = Time.strptime("2014-02-13 16:50:47 +0800", "%Y-%m-%d %H:%M:%S %z") # => 2014-02-13 16:50:47 +0800 t.class # => Time 就直接得到了Time物件了,省去了字串解析的麻煩。 如果你需要的 DateTime 物件,也可以依法炮製: require 'time' dt = DateTime.strptime("2014-02-13 16:50:47 +0800", "%Y-%m-%d %H:%M:%S %z") # => #<DateTime: 2014-02-13T16:50:47+08:00 ((2456702j,31847s,0n),+28800s,2299161j)> dt.class # => DateTime 一樣可以直接得到 DateTime 物件。 如此就可以從各式各樣的時間格式,直接產生 Time 與 DateTime 物件了。來試個怪怪的格式: time = Time.strptime("22日2008年06月...

以Ruby語言執行系統命令

以Ruby語言去執行系統命令,有下列三種方式 exec args system args %x( args ) 或 ` args ` exec args exec 會中斷目前Ruby正在進行的process,然後執行系統命令。所以這個指令還蠻少用的,可以在irb裡面試試 root$ irb 2.1.0 :001 > exec 'pwd' /Users/wemee/Documents/GitHub/test root$ irb直接被中斷掉,然後進入bash執行pwd,所以大概只能用在linux的crontab裡面,定期執行一次就中斷 system args system 則會保留目前Ruby的process,執行完系統命令後,依照執行結果回傳: true: 執行成功 false: 執行失敗,譬如移動不存在的檔案 * nil: 執行的指令本身就打錯 system 'pwd' # => true system 'mv not_exist_file.txt foo.txt' # => false system 'wrong instruction' # => nil %x( args ) 或 ` args ` 這兩個也都不會重斷Ruby的process,並且執行完後,完整回傳系統命令回傳的字串。%x( args ) 或 ` args `兩種寫法執行結果都一樣,所以我都寫` args `,而且 ruby-style-guide 也多半認為少用%x比較好。 dir = `pwd` # => dir = "/Users/root/projects\n" files = `ls` # => files = "main.rb\ntemp.txt\ntest.txt\n" 這邊可以接著用 string.chmop 把最後面字尾那個"\n"刪掉,或用用 string.gsub("\n", " ") 把所有的"\n"替換成空白欄位。 最後,執行這些指令之前,記得檢查一下你的系統唷,很多linux的指令,跟win...

Rails, 上傳圖片或其他檔案

目前網路上關於如何在Ruby on Rails上傳檔案的方式,最熱門的就屬 paperclip 。 它處理圖檔必須用到convert指令,如果是Linux系統可以用 which convert 這個指令查看一下,系統裡面有沒有convert指令。如果沒有的話paperclip是推薦用 ImageMagick ,如果你有要上傳圖檔的話,就安裝一下吧,Linux可以用rpm安裝,MacOS就直接 brew install imagemagick 。 之後就使用gem安裝paperclip, gem "paperclip" 簡易使用方式 我是使用Rails 4,以下是Rails 4的場景。 產生資料庫欄位的部分它沒有實作在rails generate指令裡面,所以必須自己先產生Model, 然後再產生一個Migration,把欄位加上去之後,做rake db:migrate,例如: # 產生 "image" Model, 以及一個欄位"title" rails g model image title:string 打開所產生的model檔案(app/models/image.rb),為它增加一個file欄位關聯 class Image < ActiveRecord::Base has_attached_file :file, styles: {medium" "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png" validates_attachment_content_type :file, content_type: /\Aimage\/.*\Z/ end 但是只是先設定好Model關聯而已,我們實際上資料庫Table裡面並沒有file欄位,我們利用migration為他增加資料庫的file欄位: # 產生一個migration 準備增加file欄位 rails g migration image_add_column...

Ruby 併行賦值(Parallel Assignment)

前言 原本在找Ruby要怎麼交換兩個陣列的位置,找到一個很神奇的方法 class Array def swap!(a,b) self[a], self[b] = self[b], self[a] self end end 完全看不懂在幹嘛,如果是C語言,在同一行裡使用逗號,則表示從右到左依次執行而已,例如: int i,j; for(i=0,j=5;i<10;i++,j--); 在C語言這個迴圈共執行10次,每次都執行i++與j--,我把i++與j--寫在一起用逗號分開,其實也可以這麼寫 int i,j; for(i=0,j=5;i<10;){ i++; j--; } 有時候為了簡潔會塞在同一行。 可是Ruby這麼做,我全看不懂在幹嘛,在文章開頭的swap!函式裡頭,self[a]在我眼裡就是回傳self[a],然後將self[b]賦值self[b]等於沒變,最後再回傳self[a]而已,完全不清楚這是怎麼swap。 Parallel Assignment 查了一下 ruby-doc.com 之後,找到了 Parallel Assignment 這個關鍵字,終於搞清楚了,Ruby會將等號右邊所有的物件,按照相對位置賦值到等號左邊的參數,就叫做 Parallel Assignment ,譬如你要將x,y,z分別賦值1,2,3,在C語言你可能這麼寫 int x=1, y=2, z=3; 在Ruby裡面可以這麼寫 x,y,z = 1,2,3 就是如此而已,x,y,z就分別被賦值1,2,3。 當然,像我這種宅宅,一定還會好好地玩弄一下,我故意讓等號兩邊無法成對: 1: a,b = 1,2,3 # a=1, b=2 2: i,j,k = 1,2 # i=1, j=2, k=nil 行1,我原本以為b會被賦值為陣列[2,3],其實不用這麼古怪,Ruby設計直接把多出來的3丟掉,聰明的設計。 行2,我原本以為會出現錯誤訊息,但這也太嚴謹了,Ruby直接讓k=nil就行了,也是聰明的設計。 接著繼續惡搞一下,看他的語法有沒有靈活性: a,b = c=1, 2 # a=1, b=2, c=1 a,b = c,d = 1, 2, 3 ...

費氏數列(Fibonacci)

Fibonacci on wiki 使用遞回 /* * @parama n 第n項(n為正整數) * @return 第n項的值 */ function fibonacci(n) if n <= 1 return n return fibonacci(n-1) + fibonacci(n-1) end 使用迭代 /* * @parama n 第n項(n為正整數) * @return 第n項的值 */ function fibonacci(n) if n <= 1 return n int a=0, b=1,t; for i = 2 to n do t = a+b a = b b = t end return b end 使用cache優化遞回 /* * @parama n 第n項(n為正整數) * @return 第n項的值 */ function fibonacci(n) static Array cache ||= {0,1} if cache[n] not null return cache[n] cache[n] = fibonacci(n-1) + fibonacci(n-1) return cache[n] end 我在Github上使用Ruby的實作 Fork me on github

Markdown to HTML(Maruku)

Maruku on Github 本文網址 純Ruby做成,可將Markdown語法轉換成HTML,latex,md...等格式,以下簡單做點介紹。 安裝 gem install maruku 先在irb下面做點測試 require 'Maruku' # => true # 設定Markdown字串 markdown_string = '#大標題' # 使用Markdown字串 建立Maruku物件 doc = Maruku.new(markdown_string) #從Maruku物件輸出HTML文檔 doc.to_html # => "\n<h1 id=\"\">大標題</h1>\n" #從Maruku物件輸出latext文檔 doc.to_latext_document # => "\\documentclass{article}\n\n% ... 至於還有哪些Methods 自己用Ruby內建的methods語法來顯示 Maruku.methods # => 一堆class methods Maruku.new.methods # => 一堆instance methods 可以再加上正規表示式來尋找 Maruku.new.methods.grep(/html/) # => 一堆HTML相關的instance methods Maruku.new.methods.grep(/latex/) # => 一堆latex相關的instance methods 與Ruby on Rails結合 在Gemfile裡面加上 gem 'maruku' 譬如你自己做個Blog,讓人使用Markdown語法來寫文章。文件從資料庫取出來,直接傳給view顯示就行了,例如文章儲存在Post資料表的content欄位 Markdown_string = Post.first.content @doc = Maruku.new(Markdown_string) 在view...

Code Block for Blogger

Code Block for Blogger 我使用Markdonw語法打部落格文章,先轉換成Html之後,在貼到Blogger去,但是闡述程式碼的Code Block的區塊,產生出來的HTML是 <pre><code> ... </pre></code> 這些HTML貼到Blooger去,因為沒有CSS樣式裝飾,所以只有簡單的換行縮排,看起來有點像 引言 。 這邊我們可以自己加上CSS Style上去,讓他看起來漂亮點。首先Markdown轉出來的code block有兩種形式,一種是嵌入式的,譬如-> int i=0; <- 直接嵌入在行內,另一種是整個程式碼區塊,譬如: int i=0; /* 程式碼自己佔一個區塊 */ 嵌入式的程式碼區塊產生的HTML會是` int i=0; 整個程式碼區塊產生的HTML會是` int i=0; 差在 <pre> tag的有無,所以我們只要分別加上這兩個CSS Style給blooger的範本,就行了。可以自己寫,不過我直接在網路上找別人做好的: <style> code { background-color: #F9F9F9; border: 1px dashed #2F6FAB; color: black; /* line-height: 1.1em; padding: 1em;*/ } pre code { display: block; /* fixes a strange ie margin bug */ font-family: Courier New; font-size: 10pt; overflow:auto; background: #f0f0f0 url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAASwCAYAAAAt7rCDAAAABHNCSVQICAgIfAhkiAAAAQJJREFUeJzt0kEKhDAMBdA4zFmbM+W0upqFOhXrDILwsimFR5pfMrXW5jhZr7PwRlxVX8//jNHrGhExjXzdu9c5IiIz+7iqVmB7Hwp4OMa2nhhwN/PRGEMBh3...