Find element in array of hashes

A

Adgar Marks

Dear all,

i am trying to find my way in Ruby, but i am just a bignner. Here is my
problem:

I have two array of hashes:

_DownloadData << { :FileName => splitLine[0] ,
:Size => splitLine[4].to_i }

_FilesData << { :FileName => splitLine[8] ,
:Year => year ,
:Month => month ,
:Day => day ,
:Suffix => suffix ,
:JDay => jday ,
:Size => splitLine[4].to_i }

I would like to know if FileName from _FileesData is in _DownloadData
and later or if the two files have the same size.

I tried to write it like this:
if _DownloadData[:FileName].include?( _FilesData[:FileName] )

and i already got an error.

what i would like to write is something like this:
_FilesData.sort_by {|hash| hash.values_at:)Year, :Month, :Day, :Suffix )
}.each do |hash|
if _DownloadData[:FileName].include?( hash[:FileName] )
index = _DownloadData[:FileName].index?( _FilesData[:FileName] )
if _DownloadData[:FileName](index) == _FilesData[:FileName]
# do something
else
# do something else
end
end
end

My questions are:
how do i fine an element of array of hashes in another array of hashes?
How do i get accuess an array of hashes at a certen index.

Thanks
 
R

Robert Klemme

Dear all,

i am trying to find my way in Ruby, but i am just a bignner. Here is my
problem:

I have two array of hashes:

_DownloadData << { :FileName => splitLine[0] ,
:Size => splitLine[4].to_i }

_FilesData << { :FileName => splitLine[8] ,
:Year => year ,
:Month => month ,
:Day => day ,
:Suffix => suffix ,
:JDay => jday ,
:Size => splitLine[4].to_i }

I assume _DownloadData and _FilesData are of type Array.
I would like to know if FileName from _FileesData is in _DownloadData
and later or if the two files have the same size.

I tried to write it like this:
if _DownloadData[:FileName].include?( _FilesData[:FileName] )

and i already got an error.

Well, if they are arrays you rather need something like this:

_DownloadData.each |dl|
x = _FilesData.find {|fl| fl[:FileName] == dl[:FileName]}
if x
# found
end
end

But note that this is inefficient if you have multiple entries in both
arrays. In that case building a hash with the file name as key could
speed up things considerably.

Btw, conventionally variables in Ruby have all lowercase names with
underscores and no leading underscore.

Kind regards

robert
 
A

Adgar Marks

Thanks for the fast answer,

Robert said:
_FilesData << { :FileName => splitLine[8] ,
:Year => year ,
:Month => month ,
:Day => day ,
:Suffix => suffix ,
:JDay => jday ,
:Size => splitLine[4].to_i }

I assume _DownloadData and _FilesData are of type Array.
I would like to know if FileName from _FileesData is in _DownloadData
and later or if the two files have the same size.

I tried to write it like this:
if _DownloadData[:FileName].include?( _FilesData[:FileName] )

and i already got an error.

Well, if they are arrays you rather need something like this:

_DownloadData.each |dl|
x = _FilesData.find {|fl| fl[:FileName] == dl[:FileName]}
if x
# found
end
end

this x, is simply "true" or "fales", it is not exactly the solution i am
searching for. I would like to find a file name from one array of hashes
in the array hashes and then to compair the file size of both identical
filenames...
But note that this is inefficient if you have multiple entries in both
arrays. In that case building a hash with the file name as key could
speed up things considerably.

Btw, conventionally variables in Ruby have all lowercase names with
underscores and no leading underscore.

Kind regards

robert

Thanks
 
R

Robert Klemme

Thanks for the fast answer,

Robert said:
_FilesData << { :FileName => splitLine[8] ,
:Year => year ,
:Month => month ,
:Day => day ,
:Suffix => suffix ,
:JDay => jday ,
:Size => splitLine[4].to_i }
I assume _DownloadData and _FilesData are of type Array.
I would like to know if FileName from _FileesData is in _DownloadData
and later or if the two files have the same size.

I tried to write it like this:
if _DownloadData[:FileName].include?( _FilesData[:FileName] )

and i already got an error.
Well, if they are arrays you rather need something like this:

_DownloadData.each |dl|
x = _FilesData.find {|fl| fl[:FileName] == dl[:FileName]}
if x
# found
end
end

this x, is simply "true" or "fales", it is not exactly the solution i am
searching for. I would like to find a file name from one array of hashes
in the array hashes and then to compair the file size of both identical
filenames...

This shows that you did not try it out or read the docs. Sorry to say that.

robert
 
A

Adgar Marks

Dear Robert,

I read your answer and also tried it!

If it would have been a simple Array, then i wouldnt have need to ask it
in the forum, because it is trivial.

Example from http://www.ruby-doc.org/core/
a = [ "a", "b", "c" ]
a.include?("b") #=> true
a.include?("z") #=> false

I read your remark:
"But note that this is inefficient if you have multiple entries in both
arrays."
whic is exaclty my case, which i tried to explain my writing:
_FilesData << { :FileName => splitLine[8] ,
:Year => year ,
:Month => month ,
:Day => day ,
:Suffix => suffix ,
:JDay => jday ,
:Size => splitLine[4].to_i }

i thought i explained my problem clearly, that my arrays are
multidimentions, by writing that they dont have the same size and
explain the structre of each Array of hashes.

I am not a Ruby expert and neither an expert programer, that is why i am
asking for help.

Thnaks
 
P

Pit Capitain

I'm not Robert, but at least we both live in the same country, so I'll
answer anyway:

2008/8/19 Adgar Marks said:
Dear Robert,

I read your answer and also tried it!

If you really tried it, then you haven't looked at the result of the
method #find. Just try each step in IRB and look at the results.
If it would have been a simple Array, then i wouldnt have need to ask it
in the forum, because it is trivial.

Example from http://www.ruby-doc.org/core/
a = [ "a", "b", "c" ]
a.include?("b") #=> true
a.include?("z") #=> false

You do have simple arrays, too, but the elements are not strings but
hashes, so you can't compare them as easily as strings. If you would
define classes for your objects with appropriate comparison methods,
then your code could look as simple as the one you've shown.
I read your remark:
"But note that this is inefficient if you have multiple entries in both
arrays."
whic is exaclty my case, which i tried to explain my writing:
...
i thought i explained my problem clearly, that my arrays are
multidimentions, by writing that they dont have the same size and
explain the structre of each Array of hashes.

I'm sure Robert understands your problem exactly, but it seems you
don't understand his answer, in which he mentioned a more efficient
data structure: hashes of hashes.
I am not a Ruby expert and neither an expert programer, that is why i am
asking for help.

From what I can tell of Robert's posts he is both a Ruby (at least an
#inject :) expert and an expert programmer, and he already gave you
the answer to your question (again: just try it) plus a hint how you
should change your data structures.

Regards,
Pit
 
R

Robert Klemme

I'm not Robert, but at least we both live in the same country, so I'll
answer anyway:

Hm, Adgar has a yahoo.de address and you claim "we both live in the same
country" - in that case I'd say all of us three live in the same
country. :))
2008/8/19 Adgar Marks <[email protected]>:

If you really tried it, then you haven't looked at the result of the
method #find. Just try each step in IRB and look at the results.

Good, then you probably want the nested Hash solution. Or rather create
a data structure for your data and put it into a Hash indexed by file
name, e.g.

FileData = Struct.new :file_name,
:year,
:month,
:day,
:suffix,
:j_day,
:size

dat = FileData.new splitLine[8], ...

I do not know what you do with that but storing the data as a Date is
probably better for consistency reasons.

Actually I'd say those Arrays are not multidimensional. Each Array
covers one dimension only but they contain complex structures (as
opposed to simple String or Fixnum).
I'm sure Robert understands your problem exactly, but it seems you
don't understand his answer, in which he mentioned a more efficient
data structure: hashes of hashes.

This was probably my fault: I was a bit too brief. I should at least
have mentioned that the object in question is returned from #find.
There was just the small "hint" that I saved it in a variable. And I
also should have mentioned IRB... :) Sorry for that, posting in a
hurry does not always yield good results.

Adgar, if you feel more comfortable with German there is also Usenet
group de.comp.lang.ruby.

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top