Subtracting one Stream from the other

Viewed 66

In Elixir, you can do the following:

iex> [1,2,3,4] -- [2,3]
[1,4]

Is there an analagous function for Stream types?

Trying to implement this, I have:

  def stream_subtract(enum, []), do: Enum.to_list(enum)

  def stream_subtract(enum1, enum2) do
    head = Stream.take(enum2, 1)
    new_enum1 = Stream.drop_while(enum1, &([&1] == head))
    stream_subtract(new_enum1, Stream.drop(enum2, 1))
  end

however this fails, as [&1] is a list, not a stream.

1 Answers

You will need to collect the second stream ahead of time so that you can test whether an element is present in it. Here's how you'd collect it into a MapSet and then filter the first stream using it.

Also, Stream.drop_while will only drop from the start of a stream. You need to use Stream.reject if you want to drop from arbitrary positions.

# Our two streams
foo = 1..10 |> Stream.take(4)
bar = 1..10 |> Stream.drop(1) |> Stream.take(2)

# Collect the second stream into a MapSet
bar = bar |> Enum.into(MapSet.new)

# Filter the first stream and print all items:
foo = foo |> Stream.reject(fn x -> x in bar end)
for f <- foo, do: IO.inspect(f)

Output:

1
4
Related