17

I have an array of Assignment objects that I create from a database call:

@assignments = @player.assignments 

I want to count them with this:

@assignments.count {|x| x.sets == 0.0}

This should count the number of assignments with 0.0 sets. However, this always returns the total number of objects in @assignments. I have checked that

@assignments.each {|x| puts x.sets == 0.0}

does not return true in all the cases. Any clues?

Edit>

@assignments.map(&:sets)
=> [35.0, 120.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.0, 75.0, 0.0, 0.0, 0.0, 0.0] 
6
  • Use select first and then count. Commented Aug 19, 2013 at 8:14
  • Can you show the output of @assignments.map(&:sets) ? Commented Aug 19, 2013 at 8:19
  • It works for me [1] pry(main)> assignments = [35.0, 120.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.0, 75.0, 0.0, 0.0, 0.0, 0.0] => [35.0, 120.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.0, 75.0, 0.0, 0.0, 0.0, 0.0] [2] pry(main)> assignments.count {|x| x == 0.0} => 9 [3] pry(main)> assignments.count => 13 Commented Aug 19, 2013 at 8:35
  • This works for me too a = [35.0, 120.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.0, 75.0, 0.0, 0.0, 0.0, 0.0] => [35.0, 120.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.0, 75.0, 0.0, 0.0, 0.0, 0.0] a.count {|x| x == 0.0} => 9 Commented Aug 19, 2013 at 8:35
  • Is this just Ruby, or is Rails involved too? Commented Aug 19, 2013 at 8:39

3 Answers 3

27

Most likely, @assignments is not an Array instance, but ActiveRecord::Relation, try @assignments.class. If so, count method does not work as you expected, it returns numbers of records.

Try

@assignments.where(sets: 0).count

Or even (convert to array first)

@assignments.to_a.count {|x| x.sets == 0.0}
Sign up to request clarification or add additional context in comments.

5 Comments

It is returned by a Rails ActiveRecord method. But @assignments.class returns Array. But your solution worked for me, so I guess it is as you say. Thank you very much!
@user1742188: Rails 2? It may say "Array" but it's not a plain array. One of the innumerable hacks that fortunately are being solved in latests versions.
Its Rails 3.2.8. Gah. Thanks for the info tokland. This was seriously crazy. The documentation should note such exceptions.
@user1742188: Paste in the question how you create @assignments. That Array thing is documented somewhere.
.all was still returning ActiveRecord::Relation for me. I had to use .all.to_a.
2

Try with this:

    @assignments.select {|x| x if x.sets == 0.0}.count

Thanks

2 Comments

This answer works for when you want to use a method to return the count. Meaning, if you're not counting based on an object's attribute, but rather based on a method. For instance: people.select {|person| person if person.tall?}.count
@singularity .select(<block>).count is really the same as count(<block>), just a little more verbose.
0

see count or each just count the number of objects only(internally it checks for each object as if object will be present it will return true if its nill will return false, so actually it counts the number of true that are returned by the block), if you want to count the number of times your condition holds true i suggest you try using the inject iterator that is made for these type of computations only in the ruby.

It will be like this

@assignments.inject(0) {|sum,x| 
  if x.sets == 0.0
    sum + 1
  else
    sum
  end
}

3 Comments

@user1742188 will you try this one too once.
In that case you should edit your answer accordingly, since as I say, the default count works exactly as OP wants it to

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.