From a555efb20fafc7eda70da5aec212223d8233b9d1 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Tue, 14 Jun 2011 21:09:50 -0400 Subject: [PATCH] New hash-based Set implementation [closes #1]. --- j/set.j | 66 +++++++++++++++---------------------------------------- j/table.j | 1 + 2 files changed, 19 insertions(+), 48 deletions(-) diff --git a/j/set.j b/j/set.j index 0ba9e6019e619..7aadfe3eb5909 100644 --- a/j/set.j +++ b/j/set.j @@ -1,58 +1,28 @@ type Set{T} - items::Array{T,1} + hash::HashTable{T,Bool} - Set() = new(Array(Any,0)) - Set{T}(T::Type) = new(Array(T,0)) + Set{T}(T::Type) = new(HashTable(T,Bool)) + Set() = Set(Any) end set{T}(x::T...) = (s = Set(T); add(s, x...)) +show(s::Set) = show_comma_array(s,'{','}') -isempty(set::Set) = isempty(set.items) -length(set::Set) = length(set.items) - -has(set::Set, x) = anyp(y->isequal(x,y), set.items) - -function add(set::Set, x) - if !has(set,x) - items = clone(set.items, length(set.items)+1) - for i = 1:length(set.items) - items[i] = set.items[i] - end - items[end] = x - set.items = items - end - set -end +isempty(s::Set) = isempty(s.hash) +length(s::Set) = length(s.hash) -add(set::Set, xs...) = (for x = xs; add(set, x); end; set) -add(set::Set, s2::Set) = (for x = s2; add(set, x); end; set) - -function del(set::Set, x) - if has(set,x) - items = clone(set.items, length(set.items)-1) - j = 1 - for i = 1:length(set.items) - if !isequal(set.items[i],x) - items[j] = set.items[i] - j += 1 - end - end - set.items = items - end - set -end +has(s::Set, x) = has(s.hash, x) -del(set::Set, xs...) = (for x = xs; del(set, x); end; set) -del(set::Set, s2::Set) = (for x = s2; del(set, x); end; set) +add(s::Set, x) = (s.hash[x] = true; s) +add(s::Set, xs...) = (for x=xs; add(s, x); end; s) +add(s::Set, s2::Set) = (for x=s2; add(s, x); end; s) -start(set::Set) = start(set.items) -done(set::Set, x) = done(set.items, x) -next(set::Set, x) = next(set.items, x) +del(s::Set, x) = (del(s.hash, x); s) +del(s::Set, xs...) = (for x=xs; del(s, x); end; s) +del(s::Set, s2::Set) = (for x=s2; del(s, x); end; s) -function union{T}(sets::Set{T}...) - u = Set(T) - for set = sets - add(u,set) - end - return u -end +start(s::Set) = start(s.hash) +done(s::Set, state) = done(s.hash, state) +next(s::Set, state) = (((k,v),state) = next(s.hash, state); (k,state)) + +union{T}(sets::Set{T}...) = (u = Set(T); for s=sets; add(u,s); end; u) diff --git a/j/table.j b/j/table.j index 01e39a3dbd99e..5781a4fe365eb 100644 --- a/j/table.j +++ b/j/table.j @@ -81,6 +81,7 @@ function hash(a::Array) h end +hash(x::Any) = uid(x) hash(s::ByteString) = ccall(:memhash32, Uint32, (Ptr{Void}, Size), s.data, length(s.data)) # hash table