[Proposal] MapSet.intersection/1 (and perhaps MapSet.union/1)

61 views
Skip to first unread message

Myron Marston

unread,
Jun 26, 2017, 6:50:51 PM6/26/17
to elixir-lang-core

I have a list of MapSets, and I want to find the intersection of all of them. When I’ve wanted to find the union of a list of MapSets, it’s felt natural to use Enum.reduce:

Enum.reduce(list_of_sets, MapSet.new, &MapSet.union/2)

To find the intersection of a list of MapSets, I wanted to use the same technique:

Enum.reduce(list_of_sets, MapSet.new, &MapSet.intersection/2)

…but that does not work, because the intersection of an empty set with another set is the empty set — so this reduction will always produce the empty set, regardless of what list_of_sets is. In fact, the starting accumulator you need is the union of all the given sets. But of course, that would be an inefficient way to go about it, as you’d reduce the list twice (once to compute the union, then again to compute the intersection, using the union as the initial accumulator). Instead, you should use a different technique:

[initial_set | rest] = list_of_sets
Enum.reduce(rest, initial_set, &MapSet.intersection/2)

While that’s not too bad, it took me some time to figure out why my initial reduction attempt did not work, and there’s no simple way to provide an initial accumulator that lets you reduce over the whole list.

One solution would be to introduce MapSet.intersection/1. Given an enumerable of sets, it would compute the intersection of all of them. This is similar to the fact that we have both Enum.concat/2 (which concats two lists), and Enum.concat/1 (which, given an enumerable of enumerables, concats them in to a single list). If we introduce MapSet.intersection/1, we may also want MapSet.union/1 for parity.

Thoughts?
Myron

James Fish

unread,
Jun 26, 2017, 7:01:04 PM6/26/17
to elixir-l...@googlegroups.com
Hi Myron,

I understand the convenience of a `MapSet.intersection/1` but there is also `Enum.reduce/2`, which is very suitable for this use case - when the accumulator is the same type as the elements of the enumerable and the first element would become the accumulator.

James

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/924446b6-9a96-4eb0-8ba4-2d47509190f3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Myron Marston

unread,
Jun 26, 2017, 7:06:20 PM6/26/17
to elixir-lang-core
Thanks, James.  Weirdly, I was thinking there might be that form of `Enum.reduce/2`, looked for it in the docs, and somehow completely skimmed past it!  I'll definitely use that, though.

--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/hk1_GoHgA-g/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CA%2BibZ9-P7%3D3Ee1Cinex9UHj8hy3gNGWW4n2J9QgfjKX7g1DbWA%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages