Elegant way to vcat vectors and remove nothing elements?

Suppose I have:

a = [1;2;3]
b = [4;5;6]
c = nothing
d = [7;8;9]

In my code, somtimes c will have values, other times it will not. I can guarantee that the type of all variables is the same. What I want is then a function to concatenate the vectors with values, so that I get:

[1;2;3;4;5;6;7;8;9]

Which is exactly what I want, since c is nothing and I don’t want it to be in there.

Is there an elegant way to achieve this?

reduce(vcat, filter(!isnothing, (a,b,c,d)))?

Thanks! I was missing reduce.


Base.vcat(n::Nothing,x)=x

Base.vcat(x,n::Nothing)=x


reduce(vcat, (a,b,c,d))

Nice, but instead of adding methods to vcat (type piracy) you could also define a wrapper changing the operator used in reduce to ignore nothing:

struct SkipNothing{F}
    op::F
end
(obj::SkipNothing)(x, y) = obj.op(x, y)
(obj::SkipNothing)(::Nothing, x) = x
(obj::SkipNothing)(x, ::Nothing) = x

reduce(SkipNothing(vcat), (a, b, c, d))

Transforming reducing functions in this fashion is precisely the idea behind Transducers:

using Transducers

foldxt(vcat, NotA(Nothing), (a, b, c, d))  # Essentially the same as above, but threaded
(a, b, c, d) |> NotA(Nothing) |> Cat() |> collect
2 Likes

I expected that there was something wrong.
But I expected, as I did, that I would learn something anyway.

I propose another

mapreduce(x->something(x,[]),vcat, (a,b,c,d))