One9.Multiset (omultiset v0.4.0-rc.0)

An unordered multiplicitous container type.

iex> mset = One9.Multiset.new(["duck", "duck", "goose"])
iex> mset |> One9.Multiset.to_counts()
%{"duck" => 2, "goose" => 1}
iex> mset |> One9.Multiset.to_list() |> Enum.sort()
["duck", "duck", "goose"]
iex> mset |> Enum.reduce(&(&2 <> &1))
"duckduckgoose"
iex> mset |> One9.Multiset.member?("spanish inquisition")
false

Summary

Functions

A more efficient alternative to Enum.to_list(ms) |> Enum.at(index).

Return the first Multiset less any copies of elements the second Multiset shares.

Return the first Multiset less any copies of elements the second Multiset shares.

Create a Multiset from any (finite) Enumerable of {t:term/0, t:non_neg_integer/0} tuples.

Create a Multiset from any (finite) Enumerable of values.

Return the intersection of two Multisets.

Create a Multiset from a MapSet, List of elements, or Map of multiplicities.

Return the cardinality of a Multiset.

Determine whether the first Multiset is a (non-strict) subset of the second.

Return the sum of two Multisets.

Convert a Multiset into a List of unique elements.

Return the cardinality of the support of a Multiset.

Convert a Multiset into a simple Map of elements to their multiplicities.

Convert a Multiset into a complete List of elements (including repeats).

Return the union of two Multisets.

Types

internal(value)

@opaque internal(value)

t()

@type t() :: t(term())

t(value)

@type t(value) :: %One9.Multiset{counts: internal(value)}

Functions

at(multiset, index)

A more efficient alternative to Enum.to_list(ms) |> Enum.at(index).

Examples

iex> One9.Multiset.from_counts(%{ # an extremely large multiset
...>   41 => 100,
...>   42 => 10**100,
...>   43 => 100
...> })
...> |> One9.Multiset.at(10**99) # pull some element out of the middle of it
42

count_element(multiset, element)

@spec count_element(t(), term()) :: non_neg_integer()

Examples

iex> One9.Multiset.new(%{a: 1, b: 2})
...> |> One9.Multiset.count_element(:b)
2

delete(multiset, element, size \\ 1)

@spec delete(t(e), term(), :all) :: t(e) when e: term()
@spec delete(t(e), term(), non_neg_integer()) :: t(e) when e: term()

Examples

iex> One9.Multiset.new(%{a: 1, b: 3})
...> |> One9.Multiset.delete(:b)
One9.Multiset.new(%{a: 1, b: 2})

iex> One9.Multiset.new(%{a: 1, b: 3})
...> |> One9.Multiset.delete(:b, 999)
One9.Multiset.new(%{a: 1})

difference(multiset1, multiset2)

@spec difference(t(e), t()) :: t(e) when e: term()

Return the first Multiset less any copies of elements the second Multiset shares.

This difference is "soft" or "clamping". See also difference!/2.

difference!(multiset1, multiset2)

@spec difference!(t(e), t(e)) :: t(e) when e: term()

Return the first Multiset less any copies of elements the second Multiset shares.

Raises if the first Multiset is not a subset of the second. See also difference/2.

empty?(multiset)

@spec empty?(t()) :: boolean()

equals?(multiset1, multiset2)

from_counts(enumerable)

@spec from_counts(One9.Ms.t0(e)) :: t(e) when e: term()

Create a Multiset from any (finite) Enumerable of {t:term/0, t:non_neg_integer/0} tuples.

Duplicate entries for the same element are accepted, and will be folded in additively.

from_elements(enumerable)

@spec from_elements(Enumerable.t(e)) :: t(e) when e: term()

Create a Multiset from any (finite) Enumerable of values.

intersection(multiset1, multiset2)

@spec intersection(t(e | e1), t(e | e2)) :: t(e)
when e: term(), e1: term(), e2: term()

Return the intersection of two Multisets.

member?(multiset, element)

@spec member?(t(), term()) :: boolean()

Examples

iex> One9.Multiset.new(%{a: 1, b: 2})
...> |> One9.Multiset.member?(:a)
true

iex> One9.Multiset.new(%{a: 1, b: 2})
...> |> One9.Multiset.member?(:z)
false

new(arg \\ [])

@spec new([e] | One9.Ms.t(e) | MapSet.t(e) | t(e)) :: t(e) when e: term()

Create a Multiset from a MapSet, List of elements, or Map of multiplicities.

To construct a Multiset from any other type, use from_counts/1 or from_elements/1 instead.

Examples

iex> One9.Multiset.new(%{"dog" => 1, "cat" => 4})
One9.Multiset.new(["dog", "cat", "cat", "cat", "cat"])

iex> One9.Multiset.new([0, 1, 2, 1])
One9.Multiset.new([0, 1, 1, 2])

iex> One9.Multiset.new(MapSet.new([0, 1, 1, 2])) # MapSet kills duplicates
One9.Multiset.new([0, 1, 2])

iex> One9.Multiset.new(%{__struct__: SomeOtherStructThatWeDontKnowTheSemanticsOf})
** (ArgumentError) explicitly call One9.Multiset.from_counts/1 or One9.Multiset.from_elements/1 instead

put(multiset, element, size \\ 1)

@spec put(t(e1), e2, pos_integer()) :: t(e1 | e2) when e1: term(), e2: term()

Examples

iex> One9.Multiset.new(%{a: 1, b: 2})
...> |> One9.Multiset.put(:b)
One9.Multiset.new(%{a: 1, b: 3})

iex> One9.Multiset.new(%{a: 1, b: 10})
...> |> One9.Multiset.put(:b, 5)
One9.Multiset.new(%{a: 1, b: 15})

size(multiset)

@spec size(t()) :: non_neg_integer()

Return the cardinality of a Multiset.

Examples

iex> One9.Multiset.new(%{a: 1, b: 2})
...> |> One9.Multiset.size()
3

See also support_size/1.

subset?(multiset1, multiset2)

@spec subset?(t(), t()) :: boolean()

Determine whether the first Multiset is a (non-strict) subset of the second.

Examples

iex> One9.Multiset.subset?(
...>   One9.Multiset.new([1, 2]),
...>   One9.Multiset.new([1, 1, 2])
...> )
true

iex> One9.Multiset.subset?(
...>   One9.Multiset.new([1, 1, 2]),
...>   One9.Multiset.new([1, 1, 2])
...> )
true

iex> One9.Multiset.subset?(
...>   One9.Multiset.new([1, 2, 2]),
...>   One9.Multiset.new([1, 1, 2])
...> )
false

sum(multiset1, multiset2)

@spec sum(t(e1), t(e2)) :: t(e1 | e2) when e1: term(), e2: term()

Return the sum of two Multisets.

support(multiset)

@spec support(t(e)) :: [e] when e: term()

Convert a Multiset into a List of unique elements.

Examples

iex> One9.Multiset.new(%{a: 1, b: 2, c: 0})
...> |> One9.Multiset.support()
...> |> Enum.sort()
[:a, :b]

support_size(multiset)

@spec support_size(t()) :: non_neg_integer()

Return the cardinality of the support of a Multiset.

See also size/1.

symmetric_difference(multiset1, multiset2)

@spec symmetric_difference(t(e1), t(e2)) :: t(e1 | e2) when e1: term(), e2: term()

Example

iex> One9.Multiset.symmetric_difference(
...>   One9.Multiset.new(%{a: 10, b:  2, c: 1}),
...>   One9.Multiset.new(%{a:  3, b: 10, c: 1})
...> )
One9.Multiset.new(%{a: 7, b: 8})

take(multiset, element, size)

@spec take(t(e), e1, non_neg_integer()) :: {t(e), [e1]} when e: term(), e1: term()

Examples

iex> One9.Multiset.new(%{a: 2, b: 3})
...> |> One9.Multiset.take(:b, 1)
{One9.Multiset.new(%{a: 2, b: 2}), [:b]}

iex> One9.Multiset.new(%{a: 2, b: 3})
...> |> One9.Multiset.take(:b, 999)
{One9.Multiset.new(%{a: 2}), [:b, :b, :b]}

to_counts(multiset)

@spec to_counts(t(e)) :: One9.Ms.t(e) when e: term()

Convert a Multiset into a simple Map of elements to their multiplicities.

Examples

iex> One9.Multiset.new([:a, :b, :b])
...> |> One9.Multiset.to_counts()
%{a: 1, b: 2}

to_list(multiset)

@spec to_list(t(e)) :: [e] when e: term()

Convert a Multiset into a complete List of elements (including repeats).

iex> One9.Multiset.new(%{a: 1, b: 2})
...> |> One9.Multiset.to_list()
...> |> Enum.sort()
[:a, :b, :b]

union(multiset1, multiset2)

@spec union(t(e1), t(e2)) :: t(e1 | e2) when e1: term(), e2: term()

Return the union of two Multisets.