2010-07-26 66 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