Feature #6367
closed#same? for Enumerable
Description
I realised that I frequently test if all objects in enumerable have the same feature. For example if all words have the same length (but not defined before). So I found particulary useful method Enumerable#same_by? that test this behaviour. I think it can be simply rewritten in C and included to Enumerable core methods.
Simple ruby implementation can be written just in a pair of lines (tests included):
module Enumerable
def same?(&block)
return true if empty?
if block_given?
first_result = yield(first)
all?{|el| first_result == yield(el)}
else
first_result = first
all?{|el| first_result == el}
end
end
end
require 'test/unit'
class TestEnumerableSame < Test::Unit::TestCase
def test_same
assert_equal(true, [1,3,9,7].same?(&:even?))
assert_equal(true, [4,8,2,2].same?(&:even?))
assert_equal(false, [1,8,3,2].same?(&:even?))
assert_equal(true, %w{cat dog rat}.same?(&:length))
assert_equal(false, %w{cat dog rabbit}.same?(&:length))
assert_equal(true, %w{cat cat cat}.same?)
assert_equal(false, %w{cat dog rat}.same?)
assert_equal(true, [].same?(&:length))
assert_equal(true, [].same?)
end
end
Updated by mame (Yusuke Endoh) over 12 years ago
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
Personally I don't think it is a good name.
It looks a kind of comparison operator.
--
Yusuke Endoh mame@tsg.ne.jp
Updated by prijutme4ty (Ilya Vorontsov) over 12 years ago
I think any name you choose can be used.
Updated by matz (Yukihiro Matsumoto) over 12 years ago
- Status changed from Assigned to Feedback
I accept the idea of having the method that ensures all elements are same (under some criteria).
But the same? is not good name for it. I place this "feedback" to get the "right" name.
Matz.
Updated by alexeymuranov (Alexey Muranov) over 12 years ago
homologous? :)
Updated by edtsech (Edward Tsech) over 12 years ago
I don't know, but I was a little bit confused by that:
assert_equal(true, [1,3,9,7].same?(&:even?))
assert_equal(true, [4,8,2,2].same?(&:even?))
or I can write smth like that:
assert_equal(true, [1.0,2.0,3.0,4.0].same?(&:integer?))
Maybe it's just unusable for "primitive" types,
because as i understand this method useful for test if all objects in enumerable have the same "property",
and "primitive" types actually don't have them.
But I like this idea:
assert_equal(true, %w{cat dog rat}.same?(&:length))
assert_equal(false, %w{cat dog rabbit}.same?(&:length))
Updated by trans (Thomas Sawyer) over 12 years ago
This reminds me of #sort and #sort_by, and I think both forms would be needed here too --where the later makes it possible to use a comparison besides #==.
On the other hand it reminds me of #all? as well, which makes me wonder about #any? too.
That leads me to think:
#all_equal?{ |a| ... }
#all_equal_by?{ |a,b| ... }
#any_equal?{ |a| ... }
#any_equal_by?{ |a,b| ... }
Updated by prijutme4ty (Ilya Vorontsov) over 12 years ago
edtsech (Edward Tsech) wrote:
I don't know, but I was a little bit confused by that:
assert_equal(true, [1,3,9,7].same?(&:even?))
assert_equal(true, [4,8,2,2].same?(&:even?))or I can write smth like that:
assert_equal(true, [1.0,2.0,3.0,4.0].same?(&:integer?))
I think renaming of method can make it less confusing. May be Enumerable#coincident?/coincident_by? or Enumerable#identical_by?
Updated by prijutme4ty (Ilya Vorontsov) over 12 years ago
trans (Thomas Sawyer) wrote:
This reminds me of #sort and #sort_by, and I think both forms would be needed here too --where the later makes it possible to use a comparison besides #==.
On the other hand it reminds me of #all? as well, which makes me wonder about #any? too.
That leads me to think:
#all_equal?{ |a| ... }
#all_equal_by?{ |a,b| ... }
#any_equal?{ |a| ... }
#any_equal_by?{ |a,b| ... }
As for me it's contrintuitive to have a pair of argument. In fact we need the only argument... or maybe I didn't understand how to use this function (and how to write the method)
Updated by trans (Thomas Sawyer) over 12 years ago
=begin
My methods names for the "_by" methods are not very good. This should clarify:
[1,1,1].all_equal? #=> true
[1,1,2].all_equal? #=> false
[2,4,6].all_equal?{|x| x*0} #=> true
[1,1,2].any_equal? #=> true
[1,2,3].any_equal? #=> false
[2,3,4].any_equal?(&:even?) #=> true
[2,4,6]#all_by?{ |a,b| a % 2 == b % 2 } #=> true
[2,3,4]#all_by?{ |a,b| a % 2 == b % 2 } #=> false
[2,3,4]#any_by?{ |a,b| a % 2 == b % 2 } #=> true
[1,2,3]#any_by?{ |a,b| a % 3 == b % 3 } #=> false
=end
Updated by pabloh (Pablo Herrero) over 12 years ago
trans (Thomas Sawyer) wrote:
My methods names for the "_by" methods are not very good. This should clarify:
[1,1,1].all_equal? #=> true
[1,1,2].all_equal? #=> false
[2,4,6].all_equal?{|x| x*0} #=> true[1,1,2].any_equal? #=> true
[1,2,3].any_equal? #=> false
Is a bit misleading about if it's using #equal? or #== for the comparison.
Updated by andhapp (Anuj Dutta) over 12 years ago
homogeneous? :)
Updated by tho119cl (Thomas Green) over 12 years ago
I like 'same_by?'
['ten', 'six', 'one', 'two'].same_by? &:length ===> true
IMO It's better to use a simple word, such as 'same', over 'identical' or 'coincident'
Updated by prijutme4ty (Ilya Vorontsov) over 12 years ago
same_by? is a good alternative. I've even replaced #same? with #same_by? in my projects.
Updated by mame (Yusuke Endoh) almost 12 years ago
- Target version set to 2.6
Updated by prijutme4ty (Ilya Vorontsov) over 11 years ago
Possible names: #same_by?, #all_equal_by?, #equal_by?, #identical_by?, #uniform_by? I think same_by? looks the most natural.
set_of_words.same_by?(&:length)
numbers.same_by{|number| number % 3 }
card_in_hand.same_by?(&:color)