Is there a combination of a struct and an array? I wanna iterate over all created objects from a cer

I have a file with many entries and much of these I don’t need. Let’s
imagine:

name=arthur
age=16
hobby=swimming
job=dancer
home=DE
name=marry
age=49
hobby=singing
job=nurse
home=US
name=tom
age=32
hobby=crafting
job=electician
home=NW
name=mantra
age=22
hobby=reading
job=cop
home=FR

this is my file and I need just the name,hobby and home of each one.

Now I read my file:

File.open(myfile).each { |line|
puts line.sub(/name=|hobby=|home=/,’’) if line =~/name|hobby|home/
}

Which puts me the entries nicly on my screen. But I have to process them
from my script. So I need some kind of an array struct which let’s me
iterate over each person and let’s me use their name,hobby and home
values. But how to achieve this? With with variable-typ and how to get
the correctly collected?

I wanna talk to them like this:

person.each |entry| do
puts entry.name
puts entry.hobby
puts entry.home
end

but how to achieve this? any idea or suggestion?

bye

kazaam wrote:

hobby=singing
job=nurse
home=US
[…]

this is my file and I need just the name,hobby and home of each one.

If the order is guaranteed, it’s as simple as
str.scan(/name=(.+?)\n.?hobby=(.+?)\n.?home=(\w+?)/m)

So I need some kind of an array struct which let’s me
iterate over each person and let’s me use their name,hobby and home values.
But how to achieve this? With with variable-typ and how to get the
correctly collected?

You don’t need “some kind of array struct” (whatever that would be) -
just an
array (which may of course contain structs).

I wanna talk to them like this:

person.each |entry| do
puts entry.name
puts entry.hobby
puts entry.home
end

Person=Struct.new(:name, :hobby, :home)
re=/name=(.+?)\n.?hobby=(.+?)\n.?home=(\w+)/m
persons=File.read(file).scan(re).map { |arr| Person.new(*arr) }
persons.each do |pers|
puts pers.name
puts pers.hobby
puts pers.home
end

A more general solution that reads in all information about a person
(even if
you don’t need it):
persons=File.read(file).scan(/name=.?(?=name=|\Z)/m).map do |pers|
Hash[pers.scan(/^(.)=(.
)$/).flatten]
end
persons.each do
puts pers[“name”]
puts pers[“hobby”]
puts pers[“home”]
end

This solution doesn’t require the order to be fixed, except that name=
has to
be the first entry for any person.

Another solution that doesn’t require any ordering in the file at all:
str=File.read(file)
Person=Struct.new(:name, :hobby, :home)
names=str.scan(/name=(.)$/).flatten
hobbies=str.scan(/hobby=(.
)$/).flatten
homes=str.scan(/home=(.*)$/).flatten
persons=names.zip(hobbies,homes).map { |pers| Person.new(*pers) }
persons.each do |pers|
puts pers.name
puts pers.hobby
puts pers.home
end

HTH,
Sebastian

On Sat, 29 Sep 2007 15:37:07 +0200, kazaam wrote:

but how to achieve this? any idea or suggestion?

maybe:
Person=Struct.new(:name,:hobby,:home)
def read_data(io)
io.gets.chomp.split(’=’)[1]
end
def read_person(io)
name= read_data(io)
hobby= read_data(io)
job=io.gets
home= read_data(io)
Person.new(name,hobby,home)
end
people=[]
people << read_person(DATA) while not DATA.eof?
puts people

or

people={}
name = nil
DATA.each do |line|
case line
when /name=(.)/
name=$1
people[name]= {‘name’=>name}
when /(hobby|home)=(.
)/
people[name][$1]=$2
end
end
p people

HTH

thanks for you’re answers I’ll work through the different approaches
now!

-------- Original-Nachricht --------

Datum: Sat, 29 Sep 2007 22:40:07 +0900
Von: kazaam [email protected]
An: [email protected]
Betreff: Is there a combination of a struct and an array? I wanna iterate over all created objects from a certain struct-class (I guess).

hobby=singing
job=cop
Which puts me the entries nicly on my screen. But I have to process them
puts entry.home
end

but how to achieve this? any idea or suggestion?

bye

kazaam [email protected]

Dear Kazaam,

you could create a class Person to do the job, something like

class Person
def initialize(name,hobby,age,job,home)
@name=name
@hobby=hobby
@age=age
@job=job
@home=home
end
def name
@name
end
def hobby
@hobby
end
def age
@age
end
def home
@home
end
def job
@job
end
end

me=Person.new(“Albert Einstein”,“physics”,134,“retired”,“wonttellyou”)
p me.hobby

There is a nice introduction to classes in Ruby in
http://pine.fm/LearnToProgram, particularly in chapter 9.

Best regards,

Axel

On Sep 29, 2007, at 7:40 AM, kazaam wrote:

hobby=singing
job=cop
home=FR

they arrayfields gem is going to make this very easy and clear:

cfp:~ > cat a.rb
require ‘enumerator’
require ‘arrayfields’ ### gem install arrayfields

re = %r/\s* ([^=]+) \s* = \s* ([^=]+) \s* \n/iomx
kvs = DATA.read.scan re

records = [] and kvs.each_slice(5){|record| records << Arrayfields
[record]}

records.each{|record| record.each_pair{|key, value| puts “#{ key } : #
{ value }”}}

END
name=arthur
age=16
hobby=swimming
job=dancer
home=DE
name=marry
age=49
hobby=singing
job=nurse
home=US
name=tom
age=32
hobby=crafting
job=electician
home=NW
name=mantra
age=22
hobby=reading
job=cop
home=FR

cfp:~ > ruby a.rb
name : arthur
age : 16
hobby : swimming
job : dancer
home : DE
name : marry
age : 49
hobby : singing
job : nurse
home : US
name : tom
age : 32
hobby : crafting
job : electician
home : NW
name : mantra
age : 22
hobby : reading
job : cop
home : FR

a @ http://drawohara.com/

On Sun, 30 Sep 2007 00:48:54 +0900, Julian T. wrote:

On 29-sep-2007, at 15:40, kazaam wrote:

but how to achieve this? any idea or suggestion?

  1. You parse the thing into a hash
  2. You use a sprinkle of _why’s Ruby magick to structify a hash

2b) you use openstruct which does it for you :slight_smile:

require ‘ostruct’
O=> true

o=OpenStruct.new(:a=>1)
=> #

o.a
=> 1

On 29-sep-2007, at 15:40, kazaam wrote:

but how to achieve this? any idea or suggestion?

  1. You parse the thing into a hash
  2. You use a sprinkle of _why’s Ruby magick to structify a hash

class H < Hash
def method_missing(m,*a)
m.to_s=~/=$/?self[$`]=a[0]:a==[]?self[m]:super
end
end

H[{:foo=>“bar”}].foo #=> “bar”

When mixed with your task, remember that you can pass a zipped array
to Hash[] (zipped means [key, val, key, val, …]), using the splat (*).
So for your person entry the example becomes:

entry = text_of_a_single_person_entry
H[ *entry.split("\n").map{|line| line.split(/=/) }.flatten.map{|
key_or_val | key_or_val.strip } ]