ruby快速阅读标准

什么是从STDIN读取多个1000000个字符(整数)的最快方法,并将其拆分为一个字符整数(不是字符串)的数组?

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

这应该相当快:

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

虽然一些粗略的基准测试显示这个hackish版本相当快:

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

我到目前为止找到的最快捷方法如下: –

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

以下是对大多数提供的解决方案进行基准测试的一些结果。 这些测试使用100,000个数字文件运行,但每个测试有10个代表。


                                  用户系统总真实
 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)
解包: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 
 scan(/\d/).map(&:to_i) 

这会将任何字符串拆分为整数数组,而忽略任何非数字字符。 如果你想从STDIN获取用户输入add gets:

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