9

これを探してみましたが、あまり見つかりませんでした。たぶん以前にも(何度も?)聞かれているような気がするので、そうでしたらすいません。

Ruby でファイルの特定の部分を解析する最速の方法は何だろうと思っていました。たとえば、特定の関数に必要な情報が、たとえば 1000 行のファイルの 500 行から 600 行の間にあることがわかっているとします。(明らかに、この種の質問は非常に大きなファイルを対象としています。例として、これらの小さな数字を使用しているだけです)、前半にはないことがわかっているので、その情報を無視する簡単な方法はありますか?

現在、私は次のようなものを使用しています:

while  buffer = file_in.gets and file_in.lineno <600
  next unless file_in.lineno > 500
  if buffer.chomp!.include? some_string
    do_func_whatever
  end
end

うまくいきますが、もっとうまくいくと思わずにはいられません。

私は Ruby に非常に慣れていないので、Ruby で新しい方法を学ぶことに興味があります。

4

4 に答える 4

11
file.lines.drop(500).take(100) # will get you lines 501-600

一般に、各行の長さが異なる可能性があるため、ファイルを最初から目的の行まで読み取ることは避けられません。ただし、回避できることの 1 つは、ファイル全体を大きな配列にロードすることです。行ごとに読み、数え、探しているものに到達するまでそれらを破棄します。あなた自身の例とほとんど同じです。より Rubyish にすることもできます。

PS。Tin Man のコメントは、私に実験をさせました。ファイル全体をロードする理由はわかりませんでしたdropが、実際には問題があります。ファイルの残りの部分を配列でdrop 返します。これを回避できる方法は次のとおりです。

file.lines.select.with_index{|l,i| (501..600) === i}

PS2: 上記のコードでは、巨大な配列を作成するのではなく、600 行未満の行であっても、ファイル全体を反復処理します。:( ここに 3 番目のバージョンがあります:

enum = file.lines
500.times{enum.next} # skip 500
enum.take(100) # take the next 100

または、FP を希望する場合:

file.lines.tap{|enum| 500.times{enum.next}}.take(100)

とにかく、このモノローグの良い点は、ファイルを反復処理する複数の方法を学べることです。;)

于 2011-02-19T19:10:35.160 に答える
1

行に対してこれを行う同等の方法があるかどうかはわかりませんが、IO オブジェクトでseekまたはoffset引数を使用して、バイトを「スキップ」できます。

IO#seekを参照するか、オフセット引数の詳細についてはIO#openを参照してください。

于 2011-02-19T18:12:03.673 に答える
0

ここではリオが役に立ちそうです。メソッドを提供しますlines()

于 2011-02-19T18:07:31.783 に答える
0

すべての行を含む配列を返すIO#readlinesを使用できます

IO.readlines(file_in)[500..600].each do |line| 
  #line is each line in the file (including the last \n)
  #stuff
end

また

f = File.new(file_in)
f.readlines[500..600].each do |line| 
  #line is each line in the file (including the last \n)
  #stuff
end
于 2011-02-19T18:09:13.460 に答える