gpt4 book ai didi

ruby - 处理这个大文本文件的最有效方法是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 08:20:49 27 4
gpt4 key购买 nike

当我将文本文件读入内存时,由于换行,它会将我的文本带入末尾的“\n”。

["Hello\n", "my\n", "name\n", "is\n", "John\n"] 

这是我阅读文本文件的方式

array = File.readlines('text_file.txt')

我需要对这个文本数组做很多处理,所以我想知道我是否应该在我第一次创建数组时删除“\n”,或者当我用正则表达式对每个元素进行处理时,性能明智的。

我写了一些(公认的错误)测试代码来删除“\n”

array = []
File.open('text_file.txt', "r").each_line do |line|
data = line.split(/\n/)
array << data
end
array.flatten!

如果我在第一次创建数组时删除“\n”,是否有更好的方法来做到这一点?

如果我想改为将文件读入 Set(为了性能),是否有类似于 readlines 的方法来做到这一点?

最佳答案

您需要运行基准测试,使用 Ruby 的内置 Benchmark找出最快的选择。

然而,根据经验,我发现“吞噬”文件,即一次读取所有文件,并不比使用 IO.foreach or File.foreach 循环更快.这是因为 Ruby 和底层操作系统在读取发生时进行文件缓冲,从而允许您的循环从内存发生,而不是直接从磁盘发生。 foreach 不会像 split 那样为您去除行终止符,因此您需要添加 chompchomp ! 如果你想改变读入的行:

File.foreach('/path/to/file') do |li|
puts li.chomp
end

File.foreach('/path/to/file') do |li|
li.chomp!
puts li
end

此外,slurping 存在不可扩展的问题;您最终可能会尝试读取一个大于内存的文件,让您的机器瘫痪,而逐行读取永远不会这样做。


这是一些性能数据:

#!/usr/bin/env ruby

require 'benchmark'
require 'fileutils'

FILENAME = 'test.txt'
LOOPS = 1

puts "Ruby Version: #{RUBY_VERSION}"
puts "Filesize being read: #{File.size(FILENAME)}"
puts "Lines in file: #{`wc -l #{FILENAME}`.split.first}"

Benchmark.bm(20) do |x|
x.report('read.split') { LOOPS.times { File.read(FILENAME).split("\n") }}
x.report('read.lines.chomp') { LOOPS.times { File.read(FILENAME).lines.map(&:chomp) }}
x.report('readlines.map.chomp1') { LOOPS.times { File.readlines(FILENAME).map(&:chomp) }}
x.report('readlines.map.chomp2') { LOOPS.times { File.readlines(FILENAME).map{ |s| s.chomp } }}
x.report('foreach.map.chomp1') { LOOPS.times { File.foreach(FILENAME).map(&:chomp) }}
x.report('foreach.map.chomp2') { LOOPS.times { File.foreach(FILENAME).map{ |s| s.chomp } }}
end

结果:

Ruby Version: 1.9.3
Filesize being read: 42026131
Lines in file: 465440
user system total real
read.split 0.150000 0.060000 0.210000 ( 0.213365)
read.lines.chomp 0.470000 0.070000 0.540000 ( 0.541266)
readlines.map.chomp1 0.450000 0.090000 0.540000 ( 0.535465)
readlines.map.chomp2 0.550000 0.060000 0.610000 ( 0.616674)
foreach.map.chomp1 0.580000 0.060000 0.640000 ( 0.641563)
foreach.map.chomp2 0.620000 0.050000 0.670000 ( 0.662912)

在当今的机器上,可以非常安全地将 42MB 的文件读入 RAM。我见过比我们某些生产主机的内存无法容纳的文件大很多的文件。虽然 foreach 速度较慢,但​​如果没有足够的内存,它也不会通过吸收所有内存而让机器瘫痪。

在 Ruby 1.9.3 上,使用 map(&:chomp) 方法,而不是旧形式的 map { |s| s.chomp },要快很多。旧版本的 Ruby 并非如此,所以买者自负。

另外,请注意,在我用了好几年的 Mac Pro 上,上述所有操作都在不到一秒的时间内处理了数据。总而言之,担心加载速度是过早的优化,真正的问题是加载数据后要做什么。

关于ruby - 处理这个大文本文件的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12412474/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com