简体   繁体   中英

Explanation of ruby code for iterating over an Array of hashes

I have two scripts both behave differently one runs one time while other twice, cant understand why can any one plz help??

SCRIPT - 1

@newArray=[{grade_id:"1",sections:"4"},
           {grade_id:"2",sections:"8"},
           {grade_id:"3",sections:"7"},
           {grade_id:"4",sections:"7"},
           {grade_id:"5",sections:"3"},
           {grade_id:"6",sections:"3"},
           {grade_id:"7",sections:"3"}]

@total_grades_passed = @newArray.count
@grades_counter = 0

while @grades_counter < @total_grades_passed do
  @newArray[@grades_counter].each do |key, value|
     print [key]
     puts [value] 
  end
  @grades_counter += 1
end

Gives below output.

[:grade_id]1
[:sections]4
[:grade_id]2
[:sections]8
[:grade_id]3
[:sections]7
[:grade_id]4
[:sections]7
[:grade_id]5
[:sections]3
[:grade_id]6
[:sections]3
[:grade_id]7
[:sections]3

While SCRIPT - 2 gives completely different output.

@newArray=[{grade_id:"1",sections:"4"},
           {grade_id:"2",sections:"8"},
           {grade_id:"3",sections:"7"},
           {grade_id:"4",sections:"7"},
           {grade_id:"5",sections:"3"},
           {grade_id:"6",sections:"3"},
           {grade_id:"7",sections:"3"}]

@total_grades_passed = @newArray.count
@grades_counter = 0  

while @grades_counter < @total_grades_passed do
  @newArray[@grades_counter].each do |x,y|
    @grade_id = @newArray[@grades_counter][:grade_id].to_i
    @no_of_sections = @newArray[@grades_counter][:sections].to_i
    puts "Grade id is #{@grade_id} and its class is #{@grade_id.class}"
    puts "section is #{@no_of_sections} and its class is #{@no_of_sections.class}"
  end
  @grades_counter += 1
end

Gives the below strange output.

Grade id is 1 and its class is Fixnum
section is 4 and its class is Fixnum
Grade id is 1 and its class is Fixnum
section is 4 and its class is Fixnum
Grade id is 2 and its class is Fixnum
section is 8 and its class is Fixnum
Grade id is 2 and its class is Fixnum
section is 8 and its class is Fixnum
Grade id is 3 and its class is Fixnum
section is 7 and its class is Fixnum
Grade id is 3 and its class is Fixnum
section is 7 and its class is Fixnum
Grade id is 4 and its class is Fixnum
section is 7 and its class is Fixnum
Grade id is 4 and its class is Fixnum
section is 7 and its class is Fixnum
Grade id is 5 and its class is Fixnum
section is 3 and its class is Fixnum
Grade id is 5 and its class is Fixnum
section is 3 and its class is Fixnum
Grade id is 6 and its class is Fixnum
section is 3 and its class is Fixnum
Grade id is 6 and its class is Fixnum
section is 3 and its class is Fixnum
Grade id is 7 and its class is Fixnum
section is 3 and its class is Fixnum
Grade id is 7 and its class is Fixnum
section is 3 and its class is Fixnum

Can anyone please explain me why this is happening, whats the difference between both scripts and their subsequent outputs are due to which lines of code? I just want to extract the grade_id and section_id and do some computation then move on to the next pair of grade and section ids and do the same computation on them.

There are better, cleaner, more "ruby-like" ways to do this.

if grade_id and sections is what you want, you could access it like this:

@newArray.each do |hash|
  hash.each do |grade_id, sections|
    # do something
  end
end

Also please note that when you iterate through a hash, it will pass as many times as there are keys. That is why your text got outputted twice.

Block code inside @newArray[@grades_counter].each will run 2 times because each hash you have 2 pairs of key-value.

And the shorter version of your code:

@newArray.each do |hash|
  hash.each do |key, value|
    print [key]
    puts [value]
  end
end

You don't want to iterate over the Hash in the second example. You're iterating over the hash keys (even though you don't use it).

You should be doing something like this:

@newArray=[{grade_id:"1",sections:"4"},{grade_id:"2",sections:"8"},
            {grade_id:"3",sections:"7"},{grade_id:"4",sections:"7"},
            {grade_id:"5",sections:"3"},{grade_id:"6",sections:"3"},
            {grade_id:"7",sections:"3"}]

@total_grades_passed = @newArray.count
@grades_counter = 0  

while @grades_counter < @total_grades_passed do

    @grade_id = @newArray[@grades_counter][:grade_id].to_i
    @no_of_sections = @newArray[@grades_counter][:sections].to_i
    puts "Grade id is #{@grade_id} and its class is #{@grade_id.class}"
    puts "section is #{@no_of_sections} and its class is #{@no_of_sections.class}"

  @grades_counter += 1
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM