David
David

Reputation: 107

Reading a line from a text file, splitting the string version of that line into two parts

Newbie learning Ruby.

I am trying to take a txt file and on each line take the first 3 characters and assign them as a key, and the rest of the string as that's keys value.

f = File.open("textfile.txt", "r")
finalHash = {"Key" => "Data"}
lineString = ""


while f.gets != nil do
  lineString = f.gets
  part1 = lineString.slice(0, 2)
  part2 = lineString.slice(3, lineString.length)
  finalHash[:part1] = part2
end

puts finalHash

Any advice is appreciated!

Upvotes: 1

Views: 251

Answers (5)

z atef
z atef

Reputation: 7679

Here you go :

Sample data:

[zatcsv]$ cat foo.txt 
TOK UPDATE DATE SHOT TIME AUXHEAT PHASE STATE PGASA PGASZ BGASA BGASZ BGASA2 BGASZ2 PIMPA
PIMPZ PELLET RGEO RMAG AMIN SEPLIM XPLIM KAPPA DELTA INDENT AREA VOL CONFIG IGRADB WALMAT DIVMAT LIMMAT EVAP 
BT IP VSURF Q95 BEPMHD BETMHD BEPDIA NEL DNELDT ZEFF PRAD POHM ENBI PINJ BSOURCE PINJ2 BSOURCE2 COCTR PNBI ECHFREQ 
ECHMODE ECHLOC PECH ICFREQ ICSCHEME ICANTEN PICRH LHFREQ LHNPAR PLH IBWFREQ PIBW TE0 TI0 WFANI WFICRH MEFF ISEQ WTH WTOT
JET 20031201 20001006 53521 1.000E+01 NBIC HSELM TRANS 2.000E+00 1.000E+00 2 1 0 0 1.658E+01 8.152E+00 NONE 2.888E+00 
HEEH OIJ OIJJ 3.047E+00 9.807E-01 2.924E-02 7.304E-02 1.572E+00 1.781E-01 0.000E+00 4.572E+00 8.161E+01 LSN 1 IN/
2.000E+06 1.013E-01 6.001E+00 1.053E+00 9.252E-01 1.128E+00 3.106E+19 3.106E+19 6.612E+00 4.515E+06 5.122E+04 1.000E+05 1.466E+07
771706 0.000E+00 652114 1.000E+00 1.420E+07 -9.999E-09 NONE NONE 0.000E+00 5.100E+07 HMIN MONOPOLE 4.027E+06 3.700E+09 1.840E+00
2.000E+06 -9.999E-09 0.000E+00 9.295E+03 1.373E+04 6.913E-01 7.319E+05 2.000E+00 NONE 3.715E+06 5.381E+06 1.282E+06 1.297E+07 1.210E+07

something like this will do it for you :

[za csv]$cat text_to_hash.rb
#!/usr/bin/env ruby

file_dir = "/dir/to_folder/foo.txt"

 thehash = Hash.new

line = File.read(file_dir).each_line do |line|

  thehash[ key = line.slice(0..2)] = val = line.slice(3..-1)

  thehash.each { |k , val| puts " Key: #{key} Value:  #{val}"} 

end

Outputs:

[za csv]$ ./text_to_hash.rb
 Key: TOK Value:   UPDATE DATE SHOT TIME AUXHEAT PHASE STATE PGASA PGASZ BGASA BGASZ BGASA2 BGASZ2 PIMPA
 Key: PIM Value:  PZ PELLET RGEO RMAG AMIN SEPLIM XPLIM KAPPA DELTA INDENT AREA VOL CONFIG IGRADB WALMAT DIVMAT LIMMAT EVAP
 Key: ECH Value:  MODE ECHLOC PECH ICFREQ ICSCHEME ICANTEN PICRH LHFREQ LHNPAR PLH IBWFREQ PIBW TE0 TI0 WFANI WFICRH MEFF ISEQ WTH WTOT
 Key: JET Value:   20031201 20001006 53521 1.000E+01 NBIC HSELM TRANS 2.000E+00 1.000E+00 2 1 0 0 1.658E+01 8.152E+00 NONE 2.888E+00 
 Key: HEE Value:  H OIJ OIJJ 3.047E+00 9.807E-01 2.924E-02 7.304E-02 1.572E+00 1.781E-01 0.000E+00 4.572E+00 8.161E+01 LSN 1 IN/
 Key: 2.0 Value:  00E+06 1.013E-01 6.001E+00 1.053E+00 9.252E-01 1.128E+00 3.106E+19 3.106E+19 6.612E+00 4.515E+06 5.122E+04 1.000E+05 1.466E+07
 Key: 771 Value:  706 0.000E+00 652114 1.000E+00 1.420E+07 -9.999E-09 NONE NONE 0.000E+00 5.100E+07 HMIN MONOPOLE 4.027E+06 3.700E+09 1.840E+00
 Key: 2.0 Value:  00E+06 -9.999E-09 0.000E+00 9.295E+03 1.373E+04 6.913E-01 7.319E+05 2.000E+00 NONE 3.715E+06 5.381E+06 1.282E+06 1.297E+07 1.210E+07
 Key: 4.4 Value:  45E-01 2.194E-01

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110665

Let's first create a file:

text = <<_
Now is the
time for all
good Rubiests
to come to the
aid of their
bowling team.
_

FName = 'temp'

File.write(FName, text)
  #=> 80

Now read the file a line at a time and construct the desired hash:

File.foreach(FName).with_object({}) do |line, h|
  h[line.slice!(0,3)] = line.chomp
end
  #=> {"Now"=>" is the", "tim"=>"e for all", "goo"=>"d Rubiests",
  #    "to "=>"come to the", "aid"=>" of their", "bow"=>"ling team."} 

After reading the first line,

h = { "Now"=>" is the" }

line = "time for all\n"

a = line.chomp
  #=> "time for all"
b = a.slice!(0,3)
  #=> "tim"
a #=> "e for all" 
h[b] = a
  #=> "e for all" 
h #=> {"Now"=>" is the", "tim"=>"e for all"}

No direction is given if a line contains fewer than three characters. That may be something to consider.

Upvotes: 1

John La Rooy
John La Rooy

Reputation: 304127

Borrowing @Cary's sample file...

text = <<_
Now is the
time for all
good Rubiests
to come to the
aid of their
bowling team.
_

FName = 'temp'

File.write(FName, text)

Now the file exists. Convert it to a 2 dimensional array. This array is trivially converted to a hash

File.foreach(FName).map{|x| [x.slice!(0,3), x]}.to_h

=> {"Now"=>" is the\n", "tim"=>"e for all\n", "goo"=>"d Rubiests\n", "to "=>"come to the\n", "aid"=>" of their\n", "bow"=>"ling team.\n"}

Upvotes: 0

boulder_ruby
boulder_ruby

Reputation: 39695

lines = File.open("textfile.txt").read.split("\n")
hsh = {}
lines.each do |line|
  next if line == ""
  hsh[line[0..2]] = line[3..-1]
end

using your method of slowly nibbling at the file

f = File.open("textfile.txt")
hsh = {}
loop do
  x = f.gets
  break unless x
  hsh[x[0..2]] = x[3..-1]
end

Upvotes: 0

Gavriel
Gavriel

Reputation: 19237

the 2nd parameter of slice is the length, not the end-index, so change:

part1 = lineString.slice(0, 2)

to:

part1 = lineString.slice(0, 3)

If passed a start index and a length, returns a substring containing length characters starting at the index

Also you don't need the second parameter here (this is not a bug though):

part2 = lineString.slice(3, lineString.length)

This is enough:

part2 = lineString.slice(3)

Upvotes: 1

Related Questions