# Re: Question about the Set class, XOR, and arrays

**URL:** <https://www.ruby-forum.com/t/re-question-about-the-set-class-xor-and-arrays/74703>\
**Category:** Ruby\
**Created:** [November 7, 2006, 10:52am UTC](https://www.ruby-forum.com/t/re-question-about-the-set-class-xor-and-arrays/74703 "2006-11-07T10:52:59Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [November 7, 2006, 10:52am UTC](https://www.ruby-forum.com/t/re-question-about-the-set-class-xor-and-arrays/74703/1 "2006-11-07T10:52:59Z")

</div>

From: Daniel B. [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

> irb(main):003:0\> Set[1,2,3] ^ [3,4,5,5]  
> =\> #\<Set: {1, 2, 4}\>
> 
> What?! I’m confused. Do I need a refresher in Set theory or something?

Looks like a bug due to Set#^'s implementation that assumes that the  
enumerable passed in has each item only once (or, due to the  
implementation, an odd number of times).

irb(main):001:0\> require ‘set’  
=\> true  
irb(main):002:0\> a = Set[1,2,3]  
=\> #\<Set: {1, 2, 3}\>  
irb(main):003:0\> a ^ [3,4,5]  
=\> #\<Set: {5, 1, 2, 4}\>  
irb(main):004:0\> a ^ [3,4,5,5]  
=\> #\<Set: {1, 2, 4}\>  
irb(main):005:0\> a ^ [3,4,5,5,5]  
=\> #\<Set: {5, 1, 2, 4}\>

The first time it sees “5”, it adds it to the resulting set. The second  
time it sees 5, it says “Oh, I already have a 5 in the result, better  
remove it.”

def ^(enum)  
enum.is\_a?(Enumerable) or raise ArgumentError, “value must be  
enumerable”  
n = dup  
enum.each { |o| if n.include?(o) then n.delete(o) else n.add(o) end  
}  
n  
end

Use #uniq on the array to get a proper answer:

irb(main):006:0\> a ^ [3,4,5,5].uniq  
=\> #\<Set: {5, 1, 2, 4}\>

---

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [November 7, 2006, 10:54am UTC](https://www.ruby-forum.com/t/re-question-about-the-set-class-xor-and-arrays/74703/2 "2006-11-07T10:54:04Z")

</div>

Hi,

At Thu, 2 Nov 2006 05:32:11 +0900,  
Gavin K. wrote:

> irb(main):001:0\> require ‘set’  
> The first time it sees “5”, it adds it to the resulting set. The second  
> time it sees 5, it says “Oh, I already have a 5 in the result, better  
> remove it.”

I’ll commit the following fix which I think is smaller and faster.  
Thanks!

# Index: set.rb

RCS file: /src/ruby/lib/set.rb,v  
retrieving revision 1.30  
diff -u -u -r1.30 set.rb  
— set.rb 2 Nov 2006 00:21:26 -0000 1.30  
+++ set.rb 2 Nov 2006 05:32:23 -0000  
@@ -294,8 +294,8 @@

# and the given enumerable object. (set ^ enum) is equivalent to

# ((set | enum) - (set & enum)).

def ^(enum)

- n = dup
- enum.each { |o| if n.include?(o) then n.delete(o) else n.add(o) end  
}

- n = Set.new(enum)
- each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }  
n  
end

–  
/  
/\_\_ \_\_ [Akinori.org](http://Akinori.org) / [MUSHA.org](http://MUSHA.org)  
/ ) ) ) ) / [FreeBSD.org](http://FreeBSD.org) / [Ruby-lang.org](http://Ruby-lang.org)  
Akinori MUSHA aka / (\_ / ( (\_\_( @ [iDaemons.org](http://iDaemons.org) / and.or.jp

“Different eyes see different things,  
Different hearts beat on different strings –  
But there are times for you and me when all such things agree”
