Reputation: 321
I'm a ruby newcomer who's trying to read a text file (a Valgrind simulation output) like this:
--------------------------------------------------------------------------------
Profile data file 'temp/gt_1024_2_16.out'
--------------------------------------------------------------------------------
I1 cache: 1024 B, 16 B, 2-way associative
D1 cache: 32768 B, 64 B, 8-way associative
LL cache: 3145728 B, 64 B, 12-way associative
Profiled target: bash run.sh
Events recorded: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
Events shown: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
Event sort order: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
Thresholds: 99 0 0 0 0 0 0 0 0
Include dirs:
User annotated:
Auto-annotation: off
--------------------------------------------------------------------------------
Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
--------------------------------------------------------------------------------
1,894,017 246,981 2,448 519,124 4,691 2,792 337,817 1,846 1,672 PROGRAM TOTALS
// other data
I want to extract the PROGRAM TOTALS table and put it into a hash. Something like...
myHash = { :Ir => 1894017, :I1mr => 246981, ILmr => 2448, ..., DLmw => 1672 }
What are the best options for doing this? Could the CSV classes help me out? Thanks a bunch.
My current code:
file = File.open(fileName, "r")
while header = file.gets
if header =~ / Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw /
# Found the header
file.gets # skip the ---- line
values = file.gets
puts "Header: " + header
puts " Data: " + values
break
end
end
I've got this output:
Header: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
Data: 1,894,017 246,981 2,448 519,124 4,691 2,792 337,817 1,846 1,672 PROGRAM TOTALS
How could I join these two strings into a hash?
Upvotes: 1
Views: 237
Reputation: 858
look at:
NAMES_INDEX = 16 # the line number of Ir I1mr ILmr Dr ...
NUMBERS_INDEX = 18 # the line number of 1,894,017 246,981 2,448 ...
FILE_NAME= "temp/gt_1024_2_16.out" # the file name
f = f = File.readlines(FILE_NAME)
names = f[NAMES_INDEX].split
numbers = f[NUMBERS_INDEX].split[0..-3].map{|a| a.delete(",").to_i}
h = Hash[names.zip numbers]
p h
Upvotes: 2
Reputation: 13901
I would write the code like this:
file_path, lines_with_data = 'data.txt', [16,18]
header, data = File.readlines(file_path)
.values_at(*lines_with_data)
.map{|line| line.strip.gsub(',','')
.split(/\s+/)}
data.map!(&:to_i)
p Hash[header.zip(data)] # => {"Ir"=>1894017, "I1mr"=>246981, "ILmr"=>2448, "Dr"=>519124, "D1mr"=>4691, "DLmr"=>2792, "Dw"=>337817, "D1mw"=>1846, "DLmw"=>1672}
Upvotes: 1
Reputation: 126722
It looks like your column names are fixed, since you search for them to find the data line.
This is how I would do it
data = nil
names = %w/ Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw /
open('E:\Perl\source\valgrind.txt', 'r') do |f|
f.each_line do |line|
if line =~ /PROGRAM TOTALS/
values = line.scan(/[\d\,]+/).map { |num| num.tr(',', '').to_i }
data = Hash[ names.zip(values) ]
break
end
end
end
p data
output
{"Ir"=>1894017, "I1mr"=>246981, "ILmr"=>2448, "Dr"=>519124, "D1mr"=>4691, "DLmr"=>2792, "Dw"=>337817, "D1mw"=>1846, "DLmw"=>1672}
Upvotes: 1