ruby 从 std 快速读取

发布于 2024-09-11 13:44:58 字数 117 浏览 5 评论 0原文

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

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

What is the fastest way to read from STDIN a number of 1000000 characters (integers), and split it into an array of one character integers (not strings) ?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一向肩并 2024-09-18 13:44:58

到目前为止,我发现的最快方法如下:-

  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

The quickest method I have found so far is as follows :-

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

Here are some results from benchmarking most of the provided solutions. These tests were run with a 100,000 digit file but with 10 reps for each test.

                                  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)

And here is the code that produced them

#!/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
孤凫 2024-09-18 13:44:58

这应该相当快:

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

尽管一些粗略的基准测试显示这个黑客版本要快得多:

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

This should be reasonably fast:

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

although some rough benchmarking shows this hackish version is considerably faster:

a = STDIN.bytes.map { |c| c-48 }
定格我的天空 2024-09-18 13:44:58
scan(/\d/).map(&:to_i)

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

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

This will split any string into an array of integers, ignoring any non-numeric characters. If you want to grab user input from STDIN add gets:

gets.scan(/\d/).map(&:to_i)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文