Skip to content

Commit

Permalink
make keys() and values() return view objects. closes #2347
Browse files Browse the repository at this point in the history
contains() should now be used for all is-element-of checking
has(d,k), for now, just does contains(keys(d),k), but is likely
to be removed or renamed haskey()
  • Loading branch information
JeffBezanson committed Apr 18, 2013
1 parent 921d515 commit da43f62
Show file tree
Hide file tree
Showing 13 changed files with 73 additions and 52 deletions.
19 changes: 11 additions & 8 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1331,9 +1331,9 @@ end

function findin(a, b)
ind = Array(Int, 0)
bset = Set(b...)
bset = add_each!(Set(), b)
for i = 1:length(a)
if has(bset, a[i])
if contains(bset, a[i])
push!(ind, i)
end
end
Expand Down Expand Up @@ -1486,14 +1486,17 @@ ctranspose{T<:Number}(x::StridedMatrix{T}) = [ conj(x[j,i]) for i=1:size(x,2), j
# set-like operators for vectors
# These are moderately efficient, preserve order, and remove dupes.

# algorithm: do intersect on sets first, then iterate through the first
# vector and produce only those in the set
function intersect(vs...)
args_type = promote_type([eltype(v) for v in vs]...)
ret = Array(args_type,0)
all_elems = intersect([Set(v...) for v in vs]...)
for v_elem in vs[1]
if has(all_elems, v_elem)
inall = true
for i = 2:length(vs)
if !contains(vs[i], v_elem)
inall=false; break
end
end
if inall
push!(ret, v_elem)
end
end
Expand All @@ -1505,7 +1508,7 @@ function union(vs...)
seen = Set()
for v in vs
for v_elem in v
if !has(seen, v_elem)
if !contains(seen, v_elem)
push!(ret, v_elem)
add!(seen, v_elem)
end
Expand All @@ -1520,7 +1523,7 @@ function setdiff(a, b)
ret = Array(args_type,0)
seen = Set()
for a_elem in a
if !has(seen, a_elem) && !has(bset, a_elem)
if !contains(seen, a_elem) && !contains(bset, a_elem)
push!(ret, a_elem)
add!(seen, a_elem)
end
Expand Down
2 changes: 1 addition & 1 deletion base/darray2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function defaultdist(dims, procs)
dims = [dims...]
chunks = ones(Int, length(dims))
np = length(procs)
f = sort!(keys(factor(np)), Sort.Reverse)
f = sort!(collect(keys(factor(np))), Sort.Reverse)
k = 1
while np > 1
# repeatedly allocate largest factor to largest dim
Expand Down
2 changes: 2 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ export PipeString
@deprecate remote_call remotecall
@deprecate remote_call_fetch remotecall_fetch
@deprecate remote_call_wait remotecall_wait
@deprecate has(s::Set, x) contains(s, x)
@deprecate has(s::IntSet, x) contains(s, x)

@deprecate expr(hd, a...) Expr(hd, a...)
@deprecate expr(hd, a::Array{Any,1}) Expr(hd, a...)
Expand Down
55 changes: 37 additions & 18 deletions base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ abstract Associative{K,V}

const secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__

has(t::Associative, key) = !is(get(t, key, secret_table_token),
secret_table_token)
has(d::Associative, k) = contains(keys(d),k)

function contains(a::Associative, p::(Any,Any))
v = get(a,p[1],secret_table_token)
!is(v, secret_table_token) && isequal(v, p[2])
end

function show{K,V}(io::IO, t::Associative{K,V})
if isempty(t)
Expand All @@ -29,25 +33,36 @@ function show{K,V}(io::IO, t::Associative{K,V})
end
end

function keys(T, a::Associative)
i = 0
keyz = Array(T,length(a))
for (k,v) in a
keyz[i+=1] = k
end
return keyz
immutable KeyIterator{T<:Associative}
dict::T
end
immutable ValueIterator{T<:Associative}
dict::T
end
keys{K,V}(a::Associative{K,V}) = keys(K,a)

function values(T, a::Associative)
i = 0
vals = Array(T,length(a))
for (k,v) in a
vals[i+=1] = v
end
return vals
length(v::Union(KeyIterator,ValueIterator)) = length(v.dict)
isempty(v::Union(KeyIterator,ValueIterator)) = isempty(v.dict)
eltype(v::KeyIterator) = eltype(v.dict)[1]
eltype(v::ValueIterator) = eltype(v.dict)[2]

start(v::Union(KeyIterator,ValueIterator)) = start(v.dict)
done(v::Union(KeyIterator,ValueIterator), state) = done(v.dict, state)

function next(v::KeyIterator, state)
n = next(v.dict, state)
n[1][1], n[2]
end

function next(v::ValueIterator, state)
n = next(v.dict, state)
n[1][2], n[2]
end
values{K,V}(a::Associative{K,V}) = values(V,a)

contains(v::KeyIterator, k) = !is(get(v.dict, k, secret_table_token),
secret_table_token)

keys(a::Associative) = KeyIterator(a)
values(a::Associative) = ValueIterator(a)

function copy(a::Associative)
b = similar(a)
Expand Down Expand Up @@ -451,6 +466,7 @@ function get{K,V}(h::Dict{K,V}, key, deflt)
end

has(h::Dict, key) = (ht_keyindex(h, key) >= 0)
contains{T<:Dict}(v::KeyIterator{T}, key) = (ht_keyindex(v.dict, key) >= 0)

function getkey{K,V}(h::Dict{K,V}, key, deflt)
index = ht_keyindex(h, key)
Expand Down Expand Up @@ -492,6 +508,9 @@ next(t::Dict, i) = ((t.keys[i],t.vals[i]), skip_deleted(t,i+1))
isempty(t::Dict) = (t.count == 0)
length(t::Dict) = t.count

next{T<:Dict}(v::KeyIterator{T}, i) = (v.dict.keys[i], skip_deleted(v.dict,i+1))
next{T<:Dict}(v::ValueIterator{T}, i) = (v.dict.vals[i], skip_deleted(v.dict,i+1))

# weak key dictionaries

function add_weak_key(t::Dict, k, v)
Expand Down
2 changes: 1 addition & 1 deletion base/env.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const ENV = EnvHash()

getindex(::EnvHash, k::String) = @accessEnv k throw(KeyError(k))
get(::EnvHash, k::String, def) = @accessEnv k (return def)
has(::EnvHash, k::String) = _hasenv(k)
contains(::KeyIterator{EnvHash}, k::String) = _hasenv(k)
delete!(::EnvHash, k::String) = (v = ENV[k]; _unsetenv(k); v)
delete!(::EnvHash, k::String, def) = has(ENV,k) ? delete!(ENV,k) : def
setindex!(::EnvHash, v, k::String) = _setenv(k,string(v))
Expand Down
2 changes: 1 addition & 1 deletion base/git.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ end

function write_config(file::String, cfg::Dict)
tmp = tempname()
for key in sort!(keys(cfg))
for key in sort!(collect(keys(cfg)))
val = cfg[key]
if isa(val,Array)
for x in val
Expand Down
2 changes: 1 addition & 1 deletion base/intset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function copy!(to::IntSet, from::IntSet)
union!(to, from)
end

function has(s::IntSet, n::Integer)
function contains(s::IntSet, n::Integer)
if n >= s.limit
s.fill1s && n >= 0
else
Expand Down
2 changes: 1 addition & 1 deletion base/meta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export quot,
quot(ex) = Expr(:quote, ex)

isexpr(ex::Expr, head) = ex.head === head
isexpr(ex::Expr, heads::Set) = has(heads, ex.head)
isexpr(ex::Expr, heads::Set) = contains(heads, ex.head)
isexpr(ex::Expr, heads::Vector) = contains(heads, ex.head)
isexpr(ex, head) = false

Expand Down
2 changes: 1 addition & 1 deletion base/pkg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ function _resolve()
end
want = Resolve.resolve(reqs,vers,deps)

pkgs = sort!(keys(merge(want,have)))
pkgs = sort!(collect(keys(merge(want,have))))
for pkg in pkgs
if has(have,pkg)
managed = cd(pkg) do
Expand Down
9 changes: 4 additions & 5 deletions base/set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ isempty(s::Set) = isempty(s.dict)
length(s::Set) = length(s.dict)
eltype{T}(s::Set{T}) = T

has(s::Set, x) = has(s.dict, x)
contains(s::Set, x) = has(s, x)
contains(s::Set, x) = has(s.dict, x)

add!(s::Set, x) = (s.dict[x] = nothing; s)
delete!(s::Set, x) = (delete!(s.dict, x); x)
Expand Down Expand Up @@ -62,7 +61,7 @@ function intersect(s::Set, sets::Set...)
i = copy(s)
for x in s
for t in sets
if !has(t,x) & has(i,x)
if !contains(t,x) & contains(i,x)
delete!(i,x)
end
end
Expand All @@ -73,7 +72,7 @@ end
function setdiff(a::Set, b::Set)
d = copy(a)
for x in b
if has(d, x)
if contains(d, x)
delete!(d, x)
end
end
Expand All @@ -88,7 +87,7 @@ isequal(l::Set, r::Set) = (length(l) == length(r)) && (l <= r)
isless(l::Set, r::Set) = (length(l) < length(r)) && (l <= r)
function <=(l::Set, r::Set)
for elt in l
if !has(r, elt)
if !contains(r, elt)
return false
end
end
Expand Down
8 changes: 4 additions & 4 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ function show_indented(io::IO, ex::Expr, indent::Int)
end
const paren_quoted_syms = Set{Symbol}(:(:),:(::),:(:=),:(=),:(==),:(===),:(=>))
function show_indented(io::IO, sym::Symbol, indent::Int)
if has(paren_quoted_syms, sym); print(io, ":($sym)")
else print(io, ":$sym")
if contains(paren_quoted_syms, sym); print(io, ":($sym)")
else print(io, ":$sym")
end
end
function default_show_quoted(io::IO, ex, indent::Int)
Expand Down Expand Up @@ -227,9 +227,9 @@ function show_unquoted(io::IO, ex::Expr, indent::Int)
show_unquoted(io, args[2], indent + indent_width)
print(io, ')')
end
elseif (has(_expr_infix, head) && nargs==2) || (is(head,:(:)) && nargs==3)
elseif (contains(_expr_infix, head) && nargs==2) || (is(head,:(:)) && nargs==3)
show_list(io, args, head, indent)
elseif has(_expr_infix_wide, head) && nargs == 2
elseif contains(_expr_infix_wide, head) && nargs == 2
show_list(io, args, " $head ", indent)
elseif is(head, symbol("::")) && nargs == 1
print(io, "::")
Expand Down
4 changes: 2 additions & 2 deletions base/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ end

# Construct a sparse vector

sparsevec{K<:Integer,V}(d::Dict{K,V}, len::Int) = sparsevec(keys(d), values(d), len)
sparsevec{K<:Integer,V}(d::Dict{K,V}, len::Int) = sparsevec(collect(keys(d)), collect(values(d)), len)

sparsevec{K<:Integer,V}(d::Dict{K,V}) = sparsevec(keys(d), values(d))
sparsevec{K<:Integer,V}(d::Dict{K,V}) = sparsevec(collect(keys(d)), collect(values(d)))

sparsevec(I::AbstractVector, V, m::Integer) = sparsevec(I, V, m, +)

Expand Down
16 changes: 7 additions & 9 deletions test/corelib.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ let
end

_d = {"a"=>0}
@test isa([k for k in filter(x->length(x)==1, keys(_d))], Vector{Any})
@test isa([k for k in filter(x->length(x)==1, collect(keys(_d)))], Vector{Any})

# issue #1821
let
Expand Down Expand Up @@ -154,7 +154,7 @@ begin
if id > 0
x = xs[id]
add!(s, x)
@test has(s, x) # check that x can be found
@test contains(s, x) # check that x can be found
else
delete!(s, xs[-id])
end
Expand Down Expand Up @@ -258,8 +258,6 @@ for i in 1:2:1000
delete!(s, i)
end
for i in 1:2:1000
@test !has(s, i)
@test has(s, i+1)
@test !contains(s, i)
@test contains(s, i+1)
end
Expand Down Expand Up @@ -351,8 +349,8 @@ c = copy(s)
@test isequal(s,c)
add!(s,100)
add!(c,200)
@test !has(c, 100)
@test !has(s, 200)
@test !contains(c, 100)
@test !contains(s, 200)

# start, done, next
for data_in in ((7,8,4,5),
Expand All @@ -368,7 +366,7 @@ for data_in in ((7,8,4,5),
t = tuple(s...)
@test length(t) == length(s)
for e in t
@test has(s,e)
@test contains(s,e)
end
end

Expand All @@ -388,8 +386,8 @@ origs = Set(1,2,3,"apple")
s = copy(origs)
for i in 1:length(origs)
el = pop!(s)
@test !has(s, el)
@test has(origs, el)
@test !contains(s, el)
@test contains(origs, el)
end
@test isempty(s)
# isequal
Expand Down

0 comments on commit da43f62

Please sign in to comment.