-1

I have:

array1 = [:blue, :blue, :blue, :blue]
array2 = [:green, :green, :yellow, :red] 

I am trying to count how many blue symbols are in array2, which is 0. I did:

near_matches = 0
array1.each do |color1|
  if array2.count(color1)
    near_matches += 1
  end
end

near_matches #=> 4

There are no matching color symbols in array1 with array2, and yet I still get 4 as an output. I was wondering why the output of my code is 4.

sawa
  • 165,429
  • 45
  • 277
  • 381
Bri Expost
  • 101
  • 8
  • Not entirely sure what you're trying to do here. 1. Is there a reason you append `each` with `with_index`? You don't use the index anywhere in your code. 2. Iterating over `array1` seems pointless since they all contain the same object, maybe this is a test array? Either way `array1.uniq` maybe the better choice to stop repeating yourself. 3. Why are you measuring the count if you're not using it anywhere? – Sagar Pandya May 15 '18 at 18:00
  • 2
    *"I am trying to count how many blue symbols are in array2"*. `array2.count(:blue) #=> 0` will do the trick. – Sagar Pandya May 15 '18 at 18:24
  • You need to explain what you are trying to do, in words, at the beginning. For example, "Given two arrays, `array1` and `array2`, and an object, `obj`, return the number of times `obj` appears in `array1`, provided `obj` appears at least once in `array2`. If `obj` does not appear in `array2`, return `0`". Note that the solution is the same regardless of the classes to which the objects belong. – Cary Swoveland May 15 '18 at 22:32
  • You are "trying to count how many blue symbols are in `array2`". Not sure how `array1` has any relevance here, and why you have `array1` in your code. – sawa May 17 '18 at 03:39

2 Answers2

3

count method returns a number, and every number is truthy in Ruby. The only non-truthy values are nil and false, so this expression

near_matches += 1

is always performed. Maybe you could do

if array2.count(color1) > 0
  near_matches += 1
end 
Ursus
  • 29,643
  • 3
  • 33
  • 50
  • `unless array2.count(color1).zero?` looks better – Ilya May 15 '18 at 17:54
  • 1
    Debatable, I'd say :) – Ursus May 15 '18 at 17:55
  • @Ilya preceded by `near_matches += 1`? – Sagar Pandya May 15 '18 at 17:55
  • `near_matches += 1 if array2.include?(color1)` may be more efficient than `count` as the former terminates as soon as one instance of `color1` is found. Both `include?` and `count` are written in C. `include?` arguably reads better as well, as it's not really the `count` that is wanted. In that regard `any?` would be even better, but it requires a block. – Cary Swoveland May 15 '18 at 20:50
  • I'm not sure this is correct. What should happen if `:blue` appears twice in `array2`? Why not simply use `near_matches += array2.count(color1)`? – Eric Duminil May 17 '18 at 07:53
  • I'm not sure too because the question is totally unclear to me. I just wanted to point out the issue. Don't mind about the algorithm the user wants to implement. – Ursus May 17 '18 at 07:54
1

nil and false are the only two values, that evaluate to false in Ruby.

ref: What evaluates to false in Ruby?

array2.count(color1) will never return nil or false so near_matches always incremented and at the end its value is equal to array1.size

you should use inject

array1.uniq.inject(0){ |sum,color| sum + array2.count(color) }
rahul mishra
  • 1,390
  • 9
  • 16
  • 1
    @sagar Pandya Thanks for formatting. I am new to StackOverflow. next time I format the content before posting. Thanks! – rahul mishra May 15 '18 at 19:35
  • @CarySwoveland sry for the late reply. I mean other than `false and nil` all values are logically evaluated to `true` ref: https://stackoverflow.com/questions/23068834/what-evaluates-to-false-in-ruby let me know if you have any different thoughts on that thanks! – rahul mishra May 17 '18 at 04:08
  • sry for the confusion have updated it. Thanks and Have a great day ahead! – rahul mishra May 17 '18 at 04:35