2010-07-26 61 views
0

什麼是從STDIN中讀取1000000個字符(整數)的最快方法,並將其分割爲一個字符整數(而不是字符串)的數組?ruby​​快速讀取std

123456 > [1,2,3,4,5,6] 

回答

2

這應該是相當快的:

a = [] 
STDIN.each_char do |c| 
    a << c.to_i 
end 

雖然有些粗糙的基準測試顯示這hackish的版本是相當快:

a = STDIN.bytes.map { |c| c-48 } 
+0

尼斯,速度遠遠超過了獲得方法,謝謝 – astropanic 2010-07-26 12:25:07

+0

尼斯過的代碼,但你如何抑制在結束-38? – astropanic 2010-07-26 12:43:53

+0

您可以對結果數組執行'[0 ... -1]',但通常情況下,除非您絕對需要它儘可能快,否則我會建議您使用一些驗證,使用'select'或'例如拒絕。如果速度至關重要,則不應該先使用Ruby。 – 2010-07-26 13:01:38

0
scan(/\d/).map(&:to_i) 

這將任何字符串分割成一個數組整數,忽略任何非數字字符。如果你想抓住從STDIN用戶輸入的添加得到:

gets.scan(/\d/).map(&:to_i) 
5

到目前爲止,我已經找到了最快捷的方法如下: -

gets.unpack("c*").map { |c| c-48} 

下面是標杆大多數提供的解決方案的一些結果。這些測試使用100,000數字文件運行,但每次測試使用10次。

 

            user  system  total  real 
each_char_full_array:   1.780000 0.010000 1.790000 ( 1.788893) 
each_char_empty_array:  1.560000 0.010000 1.570000 ( 1.572162) 
map_byte:      0.760000 0.010000 0.770000 ( 0.773848) 
gets_scan      2.220000 0.030000 2.250000 ( 2.250076) 
unpack:      0.510000 0.020000 0.530000 ( 0.529376) 

這裏是產生這些

#!/usr/bin/env ruby 

require "benchmark" 

MAX_ITERATIONS = 100000 
FILE_NAME = "1_million_digits" 

def build_test_file 
    File.open(FILE_NAME, "w") do |f| 
    MAX_ITERATIONS.times {|x| f.syswrite rand(10)} 
    end 
end 

def each_char_empty_array 
    STDIN.reopen(FILE_NAME) 
    a = [] 
    STDIN.each_char do |c| 
    a << c.to_i 
    end 
    a 
end 

def each_char_full_array 
    STDIN.reopen(FILE_NAME) 
    a = Array.new(MAX_ITERATIONS) 
    idx = 0 
    STDIN.each_char do |c| 
    a[idx] = c.to_i 
    idx += 1 
    end 
    a 
end 

def map_byte() 
    STDIN.reopen(FILE_NAME) 
    a = STDIN.bytes.map { |c| c-48 } 
    a[-1] == -38 && a.pop 
    a 
end 

def gets_scan 
    STDIN.reopen(FILE_NAME) 
    gets.scan(/\d/).map(&:to_i) 
end 


def unpack 
    STDIN.reopen(FILE_NAME) 
    gets.unpack("c*").map { |c| c-48} 
end 

reps = 10 
build_test_file 
Benchmark.bm(10) do |x| 
    x.report("each_char_full_array: ") { reps.times {|y| each_char_full_array}} 
    x.report("each_char_empty_array:") { reps.times {|y| each_char_empty_array}} 
    x.report("map_byte:    ") { reps.times {|y| map_byte}} 
    x.report("gets_scan    ") { reps.times {|y| gets_scan}} 
    x.report("unpack:    ") { reps.times {|y| unpack}} 
end 
+0

什麼是最快的方式來獲取像0 10 \ n 89 23 \ n 45 32 \ n 3 54等座標線的座標,並創建每個點的Point對象Point.new(firstnum,secondnum) – Evan 2011-08-10 16:55:44