Split into hash

Ok guys, I have a file which looks something like this:

one=1
two=2
three=something
four=something else

I want to read each line into a hash, key=value…

I have tried something like

File.open(‘file’).each do |line|
line.split(/=/){|a,b| #something}

but that’s kind of how far i get… The only way i know of is reading
them all into an array of arrays and turning that into a hash, Is there
a better idea?

Thanks in advance

Ok now i have

a = Hash.new
File.open(‘file’).each do |line|
b,c = line.split(/=/)
a[b] = c
end

Which works, but im sure there are better ways out there?

Lee J. wrote:

Ok guys, I have a file which looks something like this:

one=1
two=2
three=something
four=something else

I want to read each line into a hash, key=value…

Hash[File.read(filename).scan(/^.=.*$/).flatten]

HTH,
Sebastian

two=2
three=something
four=something else

I want to read each line into a hash, key=value…

Hash[File.read(filename).scan(/^.=.*$/).flatten]

I believe that should be:

Hash[File.read(filename).scan(/^(.)=(.*)$/).flatten]

Also, the larger the file is, the better the OP’s solution (slightly
changed
by a chomp to get rid of newlines):

a = Hash.new
File.open(‘file’).each do |line|
b,c = line.chomp.split(/=/)
a[b] = c
End

will scale. Here’s a test with 100_000 key/value pairs:

$ for a in seq 1 100000; do echo “$a=$a” >> keyval; done
$ irb
irb(main):001:0> require ‘benchmark’
=> true
irb(main):002:0> Benchmark.bm do |x|
irb(main):003:1* x.report {
irb(main):004:2* a = Hash.new
irb(main):005:2> File.open(‘keyval’).each do |line|
irb(main):006:3* b,c = line.chomp.split(/=/)
irb(main):007:3> a[b] = c
irb(main):008:3> end
irb(main):009:2> }
irb(main):010:1> x.report {
irb(main):011:2* Hash[File.read(‘keyval’).scan(/^(.)=(.*)$/).flatten]
irb(main):012:2> }
irb(main):013:1> end
user system total real
0.640000 0.020000 0.660000 ( 0.665282)
5.410000 0.030000 5.440000 ( 5.433251)
=> true
irb(main):014:0>

Though for 10_000 pairs both versions run at about the same speed on my
system, and for 1_000 the regex scanner is slightly faster. So I suppose
it’ll depend on the use case.

HTH,
Sebastian

NP: Black Sabbath - Dirty Women
Jabber: [email protected]
ICQ: 205544826

Felix

Felix W. wrote:

From: Sebastian H. [mailto:[email protected]]
Hash[File.read(filename).scan(/^.=.*$/).flatten]

I believe that should be:

Hash[File.read(filename).scan(/^(.)=(.*)$/).flatten]

Yes, it should - sorry about that. Usually I test code before posting
it.

On Mon, 24 Sep 2007 04:41:29 +0900, David A. Black wrote:

Hash[File.read(filename).scan(/^(.)=(.*)$/).flatten]

Yes, it should - sorry about that. Usually I test code before posting
it.

I think it’s exactly (?) equivalent to:

Hash[*File.read(filename).scan(/[^=\n]+/)]

if you want to save the flattening operation.

No it’s not. The difference is when there are multiple equals signs on a
single line, the first solution will only split on one, while your
solution will split on all.

Hi –

On Mon, 24 Sep 2007, Sebastian H. wrote:

Felix W. wrote:

From: Sebastian H. [mailto:[email protected]]
Hash[File.read(filename).scan(/^.=.*$/).flatten]

I believe that should be:

Hash[File.read(filename).scan(/^(.)=(.*)$/).flatten]

Yes, it should - sorry about that. Usually I test code before posting it.

I think it’s exactly (?) equivalent to:

Hash[*File.read(filename).scan(/[^=\n]+/)]

if you want to save the flattening operation.

David

Thanks very much everyone, That’s a great help

On 24.09.2007 11:11, Lee J. wrote:

Thanks very much everyone, That’s a great help

Here’s another one:

h = {}
File.foreach(“file”) do |line|
h[$1]=$2 if /^([^=])=([^=])$/ =~ line
end

Kind regards

robert