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

**URL:** <https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870>\
**Category:** Ruby\
**Created:** [September 29, 2007, 3:41pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870 "2007-09-29T15:41:08Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 29, 2007, 3:41pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/1 "2007-09-29T15:41:08Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 29, 2007, 4:27pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/2 "2007-09-29T16:27:00Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 29, 2007, 4:56pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/3 "2007-09-29T16:56:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 29, 2007, 5:15pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/4 "2007-09-29T17:15:55Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 29, 2007, 4:58pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/5 "2007-09-29T16:58:55Z")

</div>

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

> Datum: Sat, 29 Sep 2007 22:40:07 +0900  
> Von: kazaam [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> An: removed\_email\_address@domain.invalid  
> 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 [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

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](http://pine.fm/LearnToProgram), particularly in chapter 9.

Best regards,

Axel

---

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 29, 2007, 6:17pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/6 "2007-09-29T18:17:42Z")

</div>

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/](http://drawohara.com/)

---

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 30, 2007, 1:45am UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/7 "2007-09-30T01:45:34Z")

</div>

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 🙂

> > require ‘ostruct’  
> > O=\> true
> 
> > o=OpenStruct.new(:a=\>1)  
> > =\> #
> 
> > o.a  
> > =\> 1

---

<div class="post-metadata">

**Author:** ![kazaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kazaam](https://www.ruby-forum.com/u/kazaam)\
**Post date:** [September 29, 2007, 5:49pm UTC](https://www.ruby-forum.com/t/is-there-a-combination-of-a-struct-and-an-array-i-wanna-iterate-over-all-created-objects-from-a-cer/115870/8 "2007-09-29T17:49:36Z")

</div>

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 } ]
