[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

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

Gavin Kistner

11/1/2006 8:32:00 PM

From: Daniel Berger [mailto:djberg96@gmail.com]
> 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}>

1 Answer

Akinori MUSHA

11/2/2006 5:35:00 AM

0

Hi,

At Thu, 2 Nov 2006 05:32:11 +0900,
Gavin Kistner wrote:
> From: Daniel Berger [mailto:djberg96@gmail.com]
> > 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."

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 / MUSHA.org
/ ) ) ) ) / FreeBSD.org / Ruby-lang.org
Akinori MUSHA aka / (_ / ( (__( @ 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"