Check if array contains more nils than other values
Check if array contains more nils than other values
Given an array with only odd counts:
[1,nil,nil]
[1,nil,Module,nil,2]
[1,Class.new,nil]
I would like to determine if there are nils or more non-nils. The approach I used was to make everything either true or false first. And then to determine if there are more true or false values:
[ 1,nil,nil,nil,2,3].collect val.max
#=> ArgumentError: comparison of TrueClass with false failed
The max method does not want to play nice with booleans. How can I accomplish this?
Now this might not be the best approach to determine whether there are more nils or non-nils, but this is the approach that I used.
nil
nil
I'm also unclear what the question is. The title says "true or false", your question says "truthy or false", then you say you want to count nil vs non-nil, then your code is using
!!!val
(which is surely just the same thing as !val
?) - and is therefor actually counting the truthy vs falsey values.– Tom Lord
Aug 30 at 18:33
!!!val
!val
What do you want the "result" of this method to be?
true
/false
, depending on whether there are more truthy vs falsey values??– Tom Lord
Aug 30 at 18:34
true
false
You've now been given 3 answers, all of which are wrong, because the original question was contradictory and confusing :(
– Tom Lord
Aug 30 at 19:56
Coming upon this question after several edits had been done I was perplexed why most of the answers were simply incorrect. That's what happens when you change the question after an answer has been posted. That earns a downvote from me. Incidentally, the best answer was given by @sagarpandya in a comment on Andrey's answer.
– Cary Swoveland
Aug 30 at 22:04
4 Answers
4
Given an array with only odd counts
If by that you mean that there will always be the nonequal amount of truthy/falsey values in an array, then, first of all, is not a valid input.
And here's the solution:
def truthy?(array)
falsey, truthy = array.partition(&:!)
truthy.size > falsey.size
end
You can go with oneliner if you prefer:
def truthy?(array)
array.partition(&:!).max_by(&:size).any?
end
Spec:
truthy?([1,nil,nil]) #=> false
truthy?([1,nil,nil,nil,2]) #=> false
truthy?([1,4,nil]) #=> true
truthy?([1,nil,nil]) #=> false
truthy?([1,nil,Module,nil,2]) #=> true
truthy?([1,Class.new,nil]) #=> true
It uses
Enumerable#partition
BasicObject#!
If you indeed intended to only calculate nil
s, not falsey values (as it was stated in the OP):
nil
def more_nils?(array)
array.partition(&:nil?).max_by(&:size).none?
end
Spec:
more_nils?([1,nil,nil]) #=> true
more_nils?([1,nil,nil,nil,2]) #=> true
more_nils?([1,4,nil]) #=> false
more_nils?([1,nil,nil]) #=> true
more_nils?([1,nil,Module,nil,2]) #=> false
more_nils?([1,Class.new,nil]) #=> false
It uses Object#nil?
method.
Object#nil?
Inspired by @pjs's answer:
array.sum el.negative?
Even simpler ( from @SagarPandya's comment)
array.count(nil) > array.compact.count
The question was clarified -- apparently Donoto did want to count
nil
vs non-nil
; I have no idea why they decided to convert everything to true
/false
first. Therefore this answer (while it does address the original ambiguous question) is not correct. You should be using element.nil?
instead of !element
.– Tom Lord
Aug 30 at 19:55
nil
nil
true
false
element.nil?
!element
@TomLord added
nil
version– Andrey Deineko
Aug 30 at 20:01
nil
That is a lot of work for
arr.compact.size < arr.size / 2.0
or arr.compact.size / arr.size.to_f < 0.5
– engineersmnky
Aug 30 at 20:14
arr.compact.size < arr.size / 2.0
arr.compact.size / arr.size.to_f < 0.5
@engineersmnky I am not the one to call on "Ruby" way, but would you yourself approve code review if you saw
arr.compact.size < arr.size / 2.0
introducing "magic number" (2
), operating on initial input multiple times... Well, I don't say my second and third options are any better, but I bet that most Ruby devs would accept my very first option over both you presented :) (falsey, truthy = array.partition(&:nil?); falsey.size > truthy.size
)– Andrey Deineko
Aug 30 at 20:22
arr.compact.size < arr.size / 2.0
2
falsey, truthy = array.partition(&:nil?); falsey.size > truthy.size
arr.count(nil) > arr.compact.count
– Sagar Pandya
Aug 30 at 20:31
arr.count(nil) > arr.compact.count
A fairly straightforward solution would be:
def truthy?(ary)
ary.map bool.sum > 0
end
Map entries to +/-1 based on their truthiness, sum, and see whether the sum is positive or negative.
This can deal with empty arrays, it returns false
in that case.
false
This is simpler and more efficient than the accepted answer. The accepted answer requires copying the whole array. It's easily adapted to check for nils.
– Schwern
Aug 30 at 20:42
could be simplified to
sum
with a block.– Andrey Deineko
Aug 30 at 20:49
sum
@Schwern : The solution by pjs is elegant, but while it doesn't require copying of the array, it still creates a temporary object of the same size, so maybe using
inject
would be better (or sum
, as has been suggested). Another problem is, that it produces wrong results if one of the array elements is false
. I think we should use bool.nil? ? 1 : -1
inside the block.– user1934428
Aug 31 at 6:07
inject
sum
false
bool.nil? ? 1 : -1
ary.map ... .sum
→ ary.sum ...
– Stefan
Aug 31 at 6:20
ary.map ... .sum
ary.sum ...
Here another one:
if array.size > 2*array.compact.size
# We have more nil than non-nil
end
Assuming that falsy values are nil
and false
, and everything else is truthy (as conditional statements do), you can leverage Object#itself
with Array#select
.
nil
false
Object#itself
Array#select
irb(main):013:0> ary = [1,nil,nil,false,2]
=> [1, nil, nil, false, 2]
irb(main):014:0> ary.select(&:itself).length
=> 2
irb(main):015:0> ary.reject(&:itself).length
=> 3
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Is it really the case that the array can only contain odd counts? Of course, for an even-length array, there could be an equal number of
nil
vs non-nil
-- so how would you handle that? Your example ofcontains 0 elements; 0 is an even number.
– Tom Lord
Aug 30 at 18:29