Newbie questions on processing numerical data from text files

Hi,

Hope you can help me get started with these trivial questions.
I've got a practical problem, and the Ruby cookbook to help me, but a few combinations of the two haven't produced any interesting results yet. I'd need a simple useful example to start with and then make my own variations.

Here is my practical problem:

- I open a text file, locate a line according to some keyword or line number, and change a value
- I run a fortran program
- I read a text file (output of this program), extract several numerical values and export them in a two column text file

The way I've done that so far is using bash commands such as 'awk', 'grep', ... but i need some loops and it's getting too big for a sensible bash script.

Could you help me get started in Ruby with the simpler example below?

Here is the content of "sampleTextFile.dat":

this is a meaningless line
another one

maybe this line acts as a keyword for the following data

1 3.1 (415, 19e-12)
2 6 (3, 13e-14)
1 3.1 (415, 19e-12)
2 6 (3, 13e-14)

other useless words ...

I would like to read this data in some sort of array/hash, and export the first column and the product of the last two columns to a new file "results.dat". This should be enough to understand the spirit I guess, with the probably trivial problem to call the external program.

Any advice welcome.

Many thanks in advance!

baptiste

Dear Baptiste,

welcome to Ruby!

Here is my practical problem:

- I open a text file,

(... which already exists):

interesting_text=IO.readlines(file_name)

gives you an Array, with the lines as entries

locate a line according to some keyword

interesting_text.delete_if{|line| /(r|R)uby/.match==nil}

removes all lines that don't contain the string Ruby or ruby,

or line number,

interesting_text[line_number] # (start counting at 0)

and change a value

old_value=1.2
new_value=2.4

interesting_text.sub!(value.to_s,new_value.to_s)

- I run a fortran program

result=`...` where ... is the system command you use to start
your fortran program,

- I read a text file (output of this program), extract several
numerical values

You can do the reading with IO.readlines, the extraction with a
Regexp,

and export them in a two column text file

and this via

f=File.new("my_result_file.txt","w")
f.puts formatted_text
f.close

Here is the content of "sampleTextFile.dat":

> this is a meaningless line
> another one
>
> maybe this line acts as a keyword for the following data
>

I don't know how to interpret the values in brackets in the
following line:

> 1 3.1 (415, 19e-12)

If you read the file in via IO.readlines, it's a String element
of an Array, say line="1 3.1 (415, 19e-12)"
so you could do:

numbers=line.gsub(/[\(,\)]/,'').split <= removes brackets an gives
a four element Array (of Strings), which you can turn ito numbers via
eval

number_array=line.gsub(/[\(,\)]/,'').split.map{|x| eval(x)}

Some other approach might be to assign variable names to each element
in a line

vars_names=['a','b','c','d']
array_of_hashes=
lines.each{|line|
   vals_line=line.gsub(/[\(,\)]/,'').split.map{|x| eval(x)}
   tmp={}
   vars_names.each_with_index{|var_name,index|
         tmp.store(var_name,vals_line[index])
   }
   array_of_hashes<<tmp
}

will give something like:

[{"a"=>1,"b"=>3.1,"c"=>415,"d"=>19e-12},...]

Best regards,

Axel

···

--
Ist Ihr Browser Vista-kompatibel? Jetzt die neuesten
Browser-Versionen downloaden: GMX Browser - verwenden Sie immer einen aktuellen Browser. Kostenloser Download.

How i create array under ruby?
for example need create a vector type array

···

2007/6/29, Axel Etzold <AEtzold@gmx.de>:

Dear Baptiste,

welcome to Ruby!

> Here is my practical problem:
>
> - I open a text file,

(... which already exists):

interesting_text=IO.readlines(file_name)

gives you an Array, with the lines as entries

>locate a line according to some keyword

interesting_text.delete_if{|line| /(r|R)uby/.match==nil}

removes all lines that don't contain the string Ruby or ruby,

> or line number,

interesting_text[line_number] # (start counting at 0)

> and change a value
old_value=1.2
new_value=2.4

interesting_text.sub!(value.to_s,new_value.to_s)

> - I run a fortran program

result=`...` where ... is the system command you use to start
your fortran program,

> - I read a text file (output of this program), extract several
> numerical values

You can do the reading with IO.readlines, the extraction with a
Regexp,

> and export them in a two column text file

and this via

f=File.new("my_result_file.txt","w")
f.puts formatted_text
f.close

> Here is the content of "sampleTextFile.dat":
>
> > this is a meaningless line
> > another one
> >
> > maybe this line acts as a keyword for the following data
> >

I don't know how to interpret the values in brackets in the
following line:

> > 1 3.1 (415, 19e-12)

If you read the file in via IO.readlines, it's a String element
of an Array, say line="1 3.1 (415, 19e-12)"
so you could do:

numbers=line.gsub(/[\(,\)]/,'').split <= removes brackets an gives
a four element Array (of Strings), which you can turn ito numbers via
eval

number_array=line.gsub(/[\(,\)]/,'').split.map{|x| eval(x)}

Some other approach might be to assign variable names to each element
in a line

vars_names=['a','b','c','d']
array_of_hashes=
lines.each{|line|
  vals_line=line.gsub(/[\(,\)]/,'').split.map{|x| eval(x)}
  tmp={}
  vars_names.each_with_index{|var_name,index|
        tmp.store(var_name,vals_line[index])
  }
  array_of_hashes<<tmp
}

will give something like:

[{"a"=>1,"b"=>3.1,"c"=>415,"d"=>19e-12},...]

Best regards,

Axel
--
Ist Ihr Browser Vista-kompatibel? Jetzt die neuesten
Browser-Versionen downloaden: GMX Browser - verwenden Sie immer einen aktuellen Browser. Kostenloser Download.

--
Juan Pedro Meriño Diaz
Ing de Sistema CURN

Dear Baptiste,

welcome to Ruby!

Thanks a lot!

I have a few problems though,

locate a line according to some keyword

interesting_text.delete_if{|line| /(r|R)uby/.match==nil}

removes all lines that don't contain the string Ruby or ruby,

for some reason this doesn't work for me. I get an error message:
ArgumentError: wrong number of arguments (0 for 1)

if i replace this argument with something based on line numbers rather than regexp, it's fine. Is the Regexp wrong?

and change a value

old_value=1.2
new_value=2.4

interesting_text.sub!(old_value.to_s,new_value.to_s)

I can't get that to work either :
NoMethodError: private method `sub!' called for #<Array:0x7d180>

Best regards,

Axel

The rest works fine, thanks again!

baptiste

···

On 29 Jun 2007, at 14:32, Axel Etzold wrote:

How i create array under ruby?
for example need create a vector type array

Like this:

a=
a=Array.new
a=[1,2,3]
a=[1,"a",9.0]

You can include elements from all sorts of
classes into an Array.

Best regards,

Axel

···

--
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
Ideal für Modem und ISDN: GMX Handytarife 2024 | jetzt wechseln & sparen

> interesting_text.delete_if{|line| /(r|R)uby/.match==nil}
>
> removes all lines that don't contain the string Ruby or ruby,

for some reason this doesn't work for me. I get an error message:
ArgumentError: wrong number of arguments (0 for 1)

if i replace this argument with something based on line numbers
rather than regexp, it's fine. Is the Regexp wrong?

You're right. The line should read:

interesting_text.delete_if{|line| /(r|R)uby/.match(line)==nil}

>
>> and change a value
> old_value=1.2
> new_value=2.4
>
> interesting_text.sub!(old_value.to_s,new_value.to_s)
>

I can't get that to work either :
NoMethodError: private method `sub!' called for #<Array:0x7d180>

.. and again .. sub, gsub, sub!,gsub! are for Strings ... so
either:

interesting_text=IO.readlines(file_name).to_s
interesting_text.sub!(old_value.to_s,new_value.to_s)

or , if, each line is to be processed separately,

interesting_text=IO.readlines(file_name)

new_text=interesting_text.each{|line|
line.sub(old_value.to_s,new_value.to_s)}

Sorry for the confusion.

Best regards,

Axel

···

>
>
> Best regards,
>
> Axel

The rest works fine, thanks again!

baptiste

--
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer

awesome, it works! It's all starting to make some sense now.

Thanks!

baptiste

···

On 29 Jun 2007, at 19:58, Axel Etzold wrote:

interesting_text.delete_if{|line| /(r|R)uby/.match==nil}

removes all lines that don't contain the string Ruby or ruby,

for some reason this doesn't work for me. I get an error message:
ArgumentError: wrong number of arguments (0 for 1)

if i replace this argument with something based on line numbers
rather than regexp, it's fine. Is the Regexp wrong?

You're right. The line should read:

interesting_text.delete_if{|line| /(r|R)uby/.match(line)==nil}

and change a value

old_value=1.2
new_value=2.4

interesting_text.sub!(old_value.to_s,new_value.to_s)

I can't get that to work either :
NoMethodError: private method `sub!' called for #<Array:0x7d180>

.. and again .. sub, gsub, sub!,gsub! are for Strings ... so
either:

interesting_text=IO.readlines(file_name).to_s
interesting_text.sub!(old_value.to_s,new_value.to_s)

or , if, each line is to be processed separately,

interesting_text=IO.readlines(file_name)

new_text=interesting_text.each{|line|
line.sub(old_value.to_s,new_value.to_s)}

Sorry for the confusion.

Best regards,

Axel

Best regards,

Axel

The rest works fine, thanks again!

baptiste

--
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
Ideal für Modem und ISDN: GMX Handytarife 2024 | jetzt wechseln & sparen