# Re : Set intersection with a specific criteria: a better idi

**URL:** <https://www.ruby-forum.com/t/re-set-intersection-with-a-specific-criteria-a-better-idi/105655>\
**Category:** Ruby\
**Created:** [June 1, 2007, 2:21am UTC](https://www.ruby-forum.com/t/re-set-intersection-with-a-specific-criteria-a-better-idi/105655 "2007-06-01T02:21:32Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![kuyarico](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/e36b37/32.png) [@kuyarico](https://www.ruby-forum.com/u/kuyarico)\
**Post date:** [June 1, 2007, 2:21am UTC](https://www.ruby-forum.com/t/re-set-intersection-with-a-specific-criteria-a-better-idi/105655/1 "2007-06-01T02:21:32Z")

</div>

Thanks Joel,

Do you think this could/should be added to the standard library or to  
the Facets library?

Eric.

* * *

## Eric TORREBORRE tel: +81 (0)90 5580 3280 e-mail: removed\_email\_address@domain.invalid / removed\_email\_address@domain.invalid blog: [http://etorreborre.blogspot.com](http://etorreborre.blogspot.com)

----- Message d’origine ----  
De : Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Ã€ : ruby-talk ML [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
EnvoyÃ© le : Vendredi, 1 Juin 2007, 2h21mn 21s  
Objet : Re: Set intersection with a specific criteria: a better idiom?

Eric T. wrote:

> end  
> end  
> n  
> end
> 
> I have met this requirement quite some times while scripting and I may miss something here.  
> Do you know a more idiomatic, Ruby-way of doing that?

Hm, it’s like Schwartzian transform: intersect\_by instead of sort\_by.

Your implementation looks good, but might be more efficient with:

```
   mapped = self.class.new(map{|e| property.call(e)})

```

which would make mapped a set, for faster lookups.

Also, using yield will probably be more efficient than instantiating a  
proc and calling it:

def &(enum)  
n = self.class.new  
if block\_given?  
mapped = self.class.new(map{|e| yield e})  
enum.each { |o| n.add(o) if mapped.include?(yield o) }  
else  
enum.each { |o| n.add(o) if include?(o) }  
end  
n  
end

It would be more elegant to use select than to iterate through enum  
using #each and #add to the set, but Set#select returns an Array. At the  
cost of using two iterations instead of once, you could do this:

require ‘set’

class Set  
def intersect\_by(other)  
props = self.class.new(other.map {|t| yield t})  
self.class.new(select {|t| props.include? t.prop})  
end

# Actually the following is closer to the origial:

# def intersect\_by(other)

# props = self.class.new(map {|t| yield t})

# self.class.new(other.select {|t| props.include? t.prop})

# end

alias old\_intersect &

def &(other)  
if block\_given?  
intersect\_by(other) {|t| yield t}  
else  
old\_intersect(other) {|t| yield t}  
end  
end  
end

class Test  
attr\_accessor :prop  
def initialize prop  
@prop = prop  
end  
end

s1 = Set.new([  
Test.new(1),  
Test.new(2),  
Test.new(3)  
])

s2 = Set.new([  
Test.new(2),  
Test.new(3),  
Test.new(4)  
])

p(s1.intersect\_by(s2) {|t| t.prop})  
p(Set[1,2,3]&Set[2,3,4])

**END**

#\<Set: {#\<Test:0xb79f73e4 @prop=2\>, #\<Test:0xb79f73d0 @prop=3\>}\>  
#\<Set: {2, 3}\>

–  
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

* * *

DÃ©couvrez une nouvelle faÃ§on d’obtenir des rÃ©ponses Ã toutes vos  
questions !  
Profitez des connaissances, des opinions et des expÃ©riences des  
internautes sur Yahoo! Questions/RÃ©ponses

> **[Yahoo | Mail, Weather, Search, Politics, News, Finance, Sports & Videos](https://www.yahoo.com/)**
>
> Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!
