Version of `push!(::Set,v)` which returns whether `v` was already present

Is there a function which allows me to insert an entry into a set and returns whether the entry was already present? I.e. something like

function insert!(s::Set, v)
    r = v in s
    push!(s,v)
    return r
end

The version you suggested looks fine for everyday use. If you expect that most entries will already be present, then it might be slightly faster to make the push! conditional, though this could have different results if it is possible for the keys to be == but not ===.

function insert!(s::Set, v)
    (r = v in s) || push!(s,v)
    return r
end

If speed is really, really important, and you expect most calls to return false, there’s a slightly faster possibilty relying on the internal implementation of Dict.

Here’s a better version that avoid the redundancy of hashing twice.

insert!(S::Set,i) = length(S)==length(push!(S,i))
3 Likes

You can also use tokens in

https://github.com/andyferris/Dictionaries.jl#tokens

to implement a set, avoiding the double-lookup.

1 Like

Sorry, my question wasn’t very clear. I was actually wondering whether Base Julia already provides a function like this. C++ for example does: std::map<Key,T,Compare,Allocator>::insert - cppreference.com

I don’t think Base provides an implementation. A more appropriate comparison to C++'s is probably with its hinted insert, which specifically doesn’t provide a return value. From your link:

Notes

The hinted insert (4-6) does not return a boolean in order to be signature-compatible with positional insert on sequential containers, such as std::vector::insert. This makes it possible to create generic inserters such as std::inserter. One way to check success of a hinted insert is to compare size() before and after.

1 Like