Skip to content

Commit

Permalink
add count(itr) and throw and error in count if non-boolean values are…
Browse files Browse the repository at this point in the history
… encountered (#20421)

* add count(itr) (fixes #20403) and throw and error in count if non-boolean values are encountered (fixes #20404)

* fix reliance on sum behavior of count in length(t::ImmutableDict)
  • Loading branch information
stevengj authored and ararslan committed Feb 3, 2017
1 parent 3d4b312 commit ec832e5
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 4 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ This section lists changes that do not have deprecation warnings.
that internally uses twice-precision arithmetic. These two
outcomes exhibit differences in both precision and speed.

* The `count` function no longer sums non-boolean values ([#20404])

Library improvements
--------------------

Expand Down Expand Up @@ -236,6 +238,8 @@ Library improvements

* Additional methods for `ones` and `zeros` functions to support the same signature as the `similar` function ([#19635]).

* `count` now has a `count(itr)` method equivalent to `count(identity, itr)` ([#20403]).

* Methods for `map` and `filter` with `Nullable` arguments have been
implemented; the semantics are as if the `Nullable` were a container with
zero or one elements ([#16961]).
Expand Down
1 change: 1 addition & 0 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,7 @@ function countnz(B::BitArray)
end
return n
end
count(B::BitArray) = countnz(B)

# returns the index of the next non-zero element, or 0 if all zeros
function findnext(B::BitArray, start::Integer)
Expand Down
2 changes: 1 addition & 1 deletion base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ end
start(t::ImmutableDict) = t
next{K,V}(::ImmutableDict{K,V}, t) = (Pair{K,V}(t.key, t.value), t.parent)
done(::ImmutableDict, t) = !isdefined(t, :parent)
length(t::ImmutableDict) = count(x->1, t)
length(t::ImmutableDict) = count(x->true, t)
isempty(t::ImmutableDict) = done(t, start(t))
function similar(t::ImmutableDict)
while isdefined(t, :parent)
Expand Down
16 changes: 15 additions & 1 deletion base/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -642,21 +642,35 @@ end

"""
count(p, itr) -> Integer
count(itr) -> Integer
Count the number of elements in `itr` for which predicate `p` returns `true`.
If `p` is omitted, counts the number of `true` elements in `itr` (which
should be a collection of boolean values).
```jldoctest
julia> count(i->(4<=i<=6), [2,3,4,5,6])
3
julia> count([true, false, true, true])
3
```
"""
function count(pred, itr)
n = 0
for x in itr
n += pred(x)
n += pred(x)::Bool
end
return n
end
function count(pred, a::AbstractArray)
n = 0
for i in eachindex(a)
@inbounds n += pred(a[i])::Bool
end
return n
end
count(itr) = count(identity, itr)

"""
countnz(A) -> Integer
Expand Down
1 change: 1 addition & 0 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ julia> nnz(A)
"""
nnz(S::SparseMatrixCSC) = Int(S.colptr[end]-1)
countnz(S::SparseMatrixCSC) = countnz(S.nzval)
count(S::SparseMatrixCSC) = count(S.nzval)

"""
nonzeros(A)
Expand Down
1 change: 1 addition & 0 deletions base/sparse/sparsevector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ length(x::SparseVector) = x.n
size(x::SparseVector) = (x.n,)
nnz(x::SparseVector) = length(x.nzval)
countnz(x::SparseVector) = countnz(x.nzval)
count(x::SparseVector) = count(x.nzval)
nonzeros(x::SparseVector) = x.nzval
nonzeroinds(x::SparseVector) = x.nzind

Expand Down
14 changes: 12 additions & 2 deletions test/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,18 @@ immutable SomeFunctor end

# count & countnz

@test count(x->x>0, Int[]) == 0
@test count(x->x>0, -3:5) == 5
@test count(x->x>0, Int[]) == count(Bool[]) == 0
@test count(x->x>0, -3:5) == count((-3:5) .> 0) == 5
@test count([true, true, false, true]) == count(BitVector([true, true, false, true])) == 3
@test_throws TypeError count(sqrt, [1])
@test_throws TypeError count([1])
let itr = (x for x in 1:10 if x < 7)
@test count(iseven, itr) == 3
@test_throws TypeError count(itr)
@test_throws TypeError count(sqrt, itr)
end
@test count(iseven(x) for x in 1:10 if x < 7) == 3
@test count(iseven(x) for x in 1:10 if x < -7) == 0

@test countnz(Int[]) == 0
@test countnz(Int[0]) == 0
Expand Down
1 change: 1 addition & 0 deletions test/sparse/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,7 @@ end
FI = Array(I)
@test sparse(FS[FI]) == S[I] == S[FI]
@test sum(S[FI]) + sum(S[!FI]) == sum(S)
@test countnz(I) == count(I)

sumS1 = sum(S)
sumFI = sum(S[FI])
Expand Down
2 changes: 2 additions & 0 deletions test/sparse/sparsevector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ let x = spv_x1
@test nonzeros(x) == [1.25, -0.75, 3.5]
end

@test count(SparseVector(8, [2, 5, 6], [true,false,true])) == 2

# full

for (x, xf) in [(spv_x1, x1_full)]
Expand Down

0 comments on commit ec832e5

Please sign in to comment.