Feature #6367

#same? for Enumerable

Added by Ilya Vorontsov almost 2 years ago. Updated 12 months ago.

[ruby-core:44648]
Status:Feedback
Priority:Normal
Assignee:Yukihiro Matsumoto
Category:-
Target version:next minor

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 blockgiven?
first
result = yield(first)
all?{|el| firstresult == yield(el)}
else
first
result = first
all?{|el| first_result == el}
end
end
end

require 'test/unit'
class TestEnumerableSame < Test::Unit::TestCase
def testsame
assert
equal(true, [1,3,9,7].same?(&:even?))
assertequal(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

History

#1 Updated by Yusuke Endoh almost 2 years ago

  • Status changed from Open to Assigned
  • Assignee set to 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

#2 Updated by Ilya Vorontsov almost 2 years ago

I think any name you choose can be used.

#3 Updated by Yukihiro Matsumoto almost 2 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.

#4 Updated by Alexey Muranov almost 2 years ago

homologous? :)

#5 Updated by Edward Tsech almost 2 years ago

I don't know, but I was a little bit confused by that:
assertequal(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:
assertequal(true, %w{cat dog rat}.same?(&:length))
assert
equal(false, %w{cat dog rabbit}.same?(&:length))

#6 Updated by Thomas Sawyer almost 2 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:

#allequal?{ |a| ... }
#all
equalby?{ |a,b| ... }
#any
equal?{ |a| ... }
#anyequalby?{ |a,b| ... }

#7 Updated by Ilya Vorontsov almost 2 years ago

edtsech (Edward Tsech) wrote:

I don't know, but I was a little bit confused by that:
assertequal(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?/coincidentby? or Enumerable#identicalby?

#8 Updated by Ilya Vorontsov almost 2 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:

#allequal?{ |a| ... }
#all
equalby?{ |a,b| ... }
#any
equal?{ |a| ... }
#anyequalby?{ |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)

#9 Updated by Thomas Sawyer almost 2 years ago

=begin
My methods names for the "_by" methods are not very good. This should clarify:

[1,1,1].allequal? #=> true
[1,1,2].all
equal? #=> false
[2,4,6].all_equal?{|x| x*0} #=> true

[1,1,2].anyequal? #=> true
[1,2,3].any
equal? #=> false
[2,3,4].any_equal?(&:even?) #=> true

[2,4,6]#allby?{ |a,b| a % 2 == b % 2 } #=> true
[2,3,4]#all
by?{ |a,b| a % 2 == b % 2 } #=> false

[2,3,4]#anyby?{ |a,b| a % 2 == b % 2 } #=> true
[1,2,3]#any
by?{ |a,b| a % 3 == b % 3 } #=> false

=end

#10 Updated by Pablo Herrero almost 2 years ago

trans (Thomas Sawyer) wrote:

My methods names for the "_by" methods are not very good. This should clarify:

[1,1,1].allequal? #=> true
[1,1,2].all
equal? #=> false
[2,4,6].all_equal?{|x| x*0} #=> true

[1,1,2].anyequal? #=> true
[1,2,3].any
equal? #=> false

Is a bit misleading about if it's using #equal? or #== for the comparison.

#11 Updated by Anuj Dutta almost 2 years ago

homogeneous? :)

#12 Updated by Thomas Green almost 2 years ago

I like 'sameby?'
['ten', 'six', 'one', 'two'].same
by? &:length ===> true

IMO It's better to use a simple word, such as 'same', over 'identical' or 'coincident'

#13 Updated by Ilya Vorontsov almost 2 years ago

sameby? is a good alternative. I've even replaced #same? with #sameby? in my projects.

#14 Updated by Yusuke Endoh over 1 year ago

  • Target version set to next minor

#15 Updated by Ilya Vorontsov 12 months ago

Possible names: #sameby?, #allequalby?, #equalby?, #identicalby?, #uniformby? I think sameby? looks the most natural.
set
ofwords.sameby?(&:length)
numbers.sameby{|number| number % 3 }
card
inhand.sameby?(&:color)

Also available in: Atom PDF