#include <MultiSet.h>
Public Types | |
using | ArchetypeContainerType = MultiSet |
using | TraitsType = TRAITS |
using | MultiSetOfElementType = T |
MultiSetOfElementType is just a handy copy of the T template type which this MultiSet<T, TRAITS> parameterizes counting. | |
using | value_type = typename inherited::value_type |
using | ElementEqualityComparerType = Common::ComparisonRelationDeclaration< Common::ComparisonRelationType::eEquals, function< bool(ArgByValueType< T >, ArgByValueType< T >)> > |
![]() | |
using | value_type = T |
value_type is an alias for the type iterated over - like vector<T>::value_type | |
using | iterator = Iterator< T > |
using | const_iterator = Iterator< T > |
Public Member Functions | |
MultiSet () | |
nonvirtual bool | Contains (ArgByValueType< T > item) const |
nonvirtual void | Add (ArgByValueType< T > item) |
template<IInputIterator< typename TRAITS::CountedValueType > ITERATOR_OF_ADDABLE, sentinel_for< remove_cvref_t< ITERATOR_OF_ADDABLE > > ITERATOR_OF_ADDABLE2> | |
nonvirtual void | AddAll (ITERATOR_OF_ADDABLE &&start, ITERATOR_OF_ADDABLE2 &&end) |
nonvirtual void | Remove (ArgByValueType< T > item, CounterType count=1) |
remove the argument data from the multiset. The data specified MUST exist (require) - else use RemoveIf () | |
nonvirtual size_t | RemoveIf (ArgByValueType< T > item, CounterType count=1) |
remove the argument data from the multiset (can specify remove of more than are present) - returns number actually removed (multisets never have count < 0) | |
nonvirtual void | RemoveAll () |
RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items. | |
nonvirtual void | UpdateCount (const Iterator< value_type > &i, CounterType newCount, Iterator< value_type > *nextI=nullptr) |
nonvirtual void | SetCount (ArgByValueType< T > i, CounterType newCount) |
nonvirtual CounterType | OccurrencesOf (ArgByValueType< T > item) const |
nonvirtual CounterType | TotalOccurrences () const |
nonvirtual Iterator< value_type > | erase (const Iterator< value_type > &i) |
nonvirtual void | clear () |
nonvirtual Iterable< T > | Elements () const |
nonvirtual Iterable< T > | UniqueElements () const |
nonvirtual Iterable< typename TRAITS::CountedValueType > | Top () const |
Find the most commonly occurring elements of the multiset (list with count ordered most to last) | |
nonvirtual Iterable< T > | TopElements () const |
Find the most commonly occurring elements of the multiset (list of elements - without count - ordered most to last) | |
template<typename RESULT_CONTAINER = MultiSet<T, TRAITS>, invocable< T > ELEMENT_MAPPER> requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, typename TRAITS::CountedValueType>, typename RESULT_CONTAINER::value_type> or convertible_to<invoke_result_t<ELEMENT_MAPPER, typename TRAITS::CountedValueType>, optional<typename RESULT_CONTAINER::value_type>>) | |
nonvirtual RESULT_CONTAINER | Map (ELEMENT_MAPPER &&elementMapper) const |
'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to MultiSet, and improve that case to clone properties from this rep (such is rep type, ordering, etc). | |
template<derived_from< Iterable< typename TRAITS::CountedValueType > > RESULT_CONTAINER = MultiSet<T, TRAITS>, predicate< typename TRAITS::CountedValueType > INCLUDE_PREDICATE> | |
nonvirtual RESULT_CONTAINER | Where (INCLUDE_PREDICATE &&includeIfTrue) const |
nonvirtual ElementEqualityComparerType | GetElementEqualsComparer () const |
nonvirtual bool | operator== (const MultiSet &rhs) const |
nonvirtual MultiSet & | operator+= (ArgByValueType< T > item) |
![]() | |
Iterable (const Iterable &) noexcept=default | |
Iterable are safely copyable (by value). Since Iterable uses COW, this just copies the underlying pointer and increments the reference count. | |
Iterable (Iterable &&) noexcept=default | |
Iterable are safely moveable. | |
template<IIterableOfTo< T > CONTAINER_OF_T> requires (not derived_from<remove_cvref_t<CONTAINER_OF_T>, Iterable<T>>) | |
Iterable (CONTAINER_OF_T &&from) | |
Iterable (const initializer_list< T > &from) | |
nonvirtual | operator bool () const |
nonvirtual Iterator< T > | MakeIterator () const |
Create an iterator object which can be used to traverse the 'Iterable'. | |
nonvirtual size_t | size () const |
Returns the number of items contained. | |
nonvirtual bool | empty () const |
Returns true iff size() == 0. | |
template<Common::IPotentiallyComparer< T > EQUALS_COMPARER = equal_to<T>> | |
nonvirtual bool | Contains (ArgByValueType< T > element, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const |
nonvirtual Iterator< T > | begin () const |
Support for ranged for, and STL syntax in general. | |
nonvirtual void | Apply (const function< void(ArgByValueType< T > item)> &doToElement, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const |
Run the argument function (or lambda) on each element of the container. | |
template<predicate< T > THAT_FUNCTION> | |
nonvirtual Iterator< T > | Find (THAT_FUNCTION &&that, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const |
Run the argument bool-returning function (or lambda) on each element of the container, and return an iterator pointing at the first element (depending on seq) found true. (or use First() to do same thing but return optional<>) | |
template<IIterableOfFrom< T > CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS> | |
nonvirtual CONTAINER_OF_T | As (CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const |
nonvirtual T | Nth (ptrdiff_t n) const |
Find the Nth element of the Iterable<> | |
nonvirtual T | NthValue (ptrdiff_t n, ArgByValueType< T > defaultValue={}) const |
Find the Nth element of the Iterable<>, but allow for n to be out of range, and just return argument default-value. | |
template<derived_from< Iterable< T > > RESULT_CONTAINER = Iterable<T>, predicate< T > INCLUDE_PREDICATE> | |
nonvirtual RESULT_CONTAINER | Where (INCLUDE_PREDICATE &&includeIfTrue) const |
produce a subset of this iterable where argument function returns true | |
template<Common::IPotentiallyComparer< T > EQUALS_COMPARER = equal_to<T>> | |
nonvirtual Iterable< T > | Distinct (EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const |
template<ranges::range RESULT_CONTAINER = Iterable<T>, invocable< T > ELEMENT_MAPPER> requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>) | |
nonvirtual RESULT_CONTAINER | Map (ELEMENT_MAPPER &&elementMapper) const |
functional API which iterates over all members of an Iterable, applies a map function to each element, and collects the results in a new Iterable | |
template<typename REDUCED_TYPE = T> | |
nonvirtual optional< REDUCED_TYPE > | Reduce (const function< REDUCED_TYPE(ArgByValueType< T >, ArgByValueType< T >)> &op) const |
Walk the entire list of items, and use the argument 'op' to combine (reduce) items to a resulting single item. | |
template<typename REDUCED_TYPE = T> | |
nonvirtual REDUCED_TYPE | ReduceValue (const function< REDUCED_TYPE(ArgByValueType< T >, ArgByValueType< T >)> &op, ArgByValueType< REDUCED_TYPE > defaultValue={}) const |
template<typename RESULT_T = Characters::String, invocable< T > CONVERT_TO_RESULT = decltype (kDefaultToStringConverter<>), invocable< RESULT_T, RESULT_T, bool > COMBINER = decltype (Characters::kDefaultStringCombiner)> requires (convertible_to<invoke_result_t<CONVERT_TO_RESULT, T>, RESULT_T> and convertible_to<invoke_result_t<COMBINER, RESULT_T, RESULT_T, bool>, RESULT_T>) | |
nonvirtual RESULT_T | Join (const CONVERT_TO_RESULT &convertToResult=kDefaultToStringConverter<>, const COMBINER &combiner=Characters::kDefaultStringCombiner) const |
ape the JavaScript/python 'join' function - take the parts of 'this' iterable and combine them into a new object (typically a string) | |
nonvirtual Iterable< T > | Skip (size_t nItems) const |
nonvirtual Iterable< T > | Take (size_t nItems) const |
nonvirtual Iterable< T > | Slice (size_t from, size_t to) const |
nonvirtual Iterable< T > | Top () const |
return the top/largest (possibly just top N) values from this Iterable<T> | |
template<Common::IPotentiallyComparer< T > INORDER_COMPARER_TYPE = less<T>> | |
nonvirtual Iterable< T > | OrderBy (INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}, Execution::SequencePolicy seq=Execution::SequencePolicy::ePar) const |
template<Common::IPotentiallyComparer< T > INORDER_COMPARER_TYPE = less<T>> | |
nonvirtual bool | IsOrderedBy (INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}) const |
nonvirtual optional< T > | First () const |
return first element in iterable, or if 'that' specified, first where 'that' is true, (or return nullopt if none) | |
nonvirtual T | FirstValue (ArgByValueType< T > defaultValue={}) const |
return first element in iterable provided default | |
nonvirtual optional< T > | Last () const |
return last element in iterable, or if 'that' specified, last where 'that' is true, (or return missing) | |
nonvirtual T | LastValue (ArgByValueType< T > defaultValue={}) const |
nonvirtual bool | All (const function< bool(ArgByValueType< T >)> &testEachElt) const |
return true iff argument predicate returns true for each element of the iterable | |
nonvirtual optional< T > | Min () const |
template<typename RESULT_TYPE = T> | |
nonvirtual RESULT_TYPE | MinValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const |
nonvirtual optional< T > | Max () const |
template<typename RESULT_TYPE = T> | |
nonvirtual RESULT_TYPE | MaxValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const |
template<typename RESULT_TYPE = T> | |
nonvirtual optional< RESULT_TYPE > | Mean () const |
template<typename RESULT_TYPE = T> | |
nonvirtual RESULT_TYPE | MeanValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const |
template<typename RESULT_TYPE = T> | |
nonvirtual optional< RESULT_TYPE > | Sum () const |
template<typename RESULT_TYPE = T> | |
nonvirtual RESULT_TYPE | SumValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const |
template<constructible_from< T > RESULT_TYPE = T, Common::IPotentiallyComparer< RESULT_TYPE > INORDER_COMPARE_FUNCTION = less<RESULT_TYPE>> | |
nonvirtual optional< RESULT_TYPE > | Median (const INORDER_COMPARE_FUNCTION &compare={}) const |
template<constructible_from< T > RESULT_TYPE = T> | |
nonvirtual RESULT_TYPE | MedianValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const |
nonvirtual Iterable< T > | Repeat (size_t count) const |
nonvirtual bool | Any () const |
Any() same as not empty (); Any (includeIfTrue) returns true iff includeIfTrue returns true on any values in iterable. | |
nonvirtual size_t | Count () const |
with no args, same as size, with function filter arg, returns number of items that pass. | |
nonvirtual size_t | length () const |
STL-ish alias for size() - really in STL only used in string, I think, but still makes sense as an alias. | |
Protected Member Functions | |
nonvirtual tuple< _IRep *, Iterator< value_type > > | _GetWritableRepAndPatchAssociatedIterator (const Iterator< value_type > &i) |
Utility to get WRITABLE underlying shared_ptr (replacement for what we normally do - _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ()) but where we also handle the cloning/patching of the associated iterator. | |
![]() | |
Iterable (const shared_ptr< _IRep > &rep) noexcept | |
Iterable's are typically constructed as concrete subtype objects, whose CTOR passed in a shared copyable rep. | |
nonvirtual Memory::SharedByValue_State | _GetSharingState () const |
Additional Inherited Members | |
![]() | |
template<ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>> | |
static bool | SetEquals (const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) |
template<ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>> | |
static bool | MultiSetEquals (const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) |
template<ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>> | |
static bool | SequentialEquals (const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}, bool useIterableSize=false) |
static constexpr default_sentinel_t | end () noexcept |
Support for ranged for, and STL syntax in general. | |
![]() | |
template<same_as< Characters::String > RESULT_T = Characters::String> | |
static const function< RESULT_T(T)> | kDefaultToStringConverter |
![]() | |
using | _SharedByValueRepType = Memory::SharedByValue< _IRep, Memory::SharedByValue_Traits< _IRep, shared_ptr< _IRep >, Rep_Cloner_ > > |
Lazy-copying smart pointer mostly used by implementors (can generally be ignored by users). However, protected because manipulation needed in some subclasses (rarely) - like UpdatableIteratable. | |
![]() | |
_SharedByValueRepType | _fRep |
A MultiSet<T, TRAITS> A collection of elements where each time you add something, the MultiSet tallies the number of times that thing has been entered. This is not a commonly used class, but handy when you want to count things.
MultiSet<T, TRAITS> inherits from Iterable<CountedValue<T>> instead of Iterable<T> because if you are using a MultiSet, you probably want access to the counts as you iterate - not just the unique elements (though we make it easy to get that iterator too with Elements () or UniqueElements ()).
A MultiSet<T, TRAITS> makes no promises about ordering of elements in iteration.
Concrete Implementations: o
Factory:
o Multisets intrinsically know how to compare their elements (for equality) - even if equal_to<T> not defined
Two MultiSet are considered equal if they contain the same elements (by comparing them with GetElementEqualsComparer ()) with the same count. In short, they are equal if OccurrencesOf() each item in the LHS equals the OccurrencesOf() the same item in the RHS. Note - this computation MAYBE very expensive, and not optimized (maybe do better in a future release - see TODO). @todo - document computational complexity ThreeWayComparer support is NOT provided for Multisets, because there is no intrinsic ordering among the elements of the multiset (keys) - even if there was some way to compare the T elements.
Definition at line 113 of file MultiSet.h.
using Stroika::Foundation::Containers::MultiSet< T, TRAITS >::ArchetypeContainerType = MultiSet |
Use this typedef in templates to recover the basic functional container pattern of concrete types.
Definition at line 121 of file MultiSet.h.
using Stroika::Foundation::Containers::MultiSet< T, TRAITS >::TraitsType = TRAITS |
Just a short-hand for the 'TRAITS' part of MultiSet<T,TRAITS>. This is often handy to use in building other templates.
Definition at line 128 of file MultiSet.h.
using Stroika::Foundation::Containers::MultiSet< T, TRAITS >::value_type = typename inherited::value_type |
typename TRAITS::CountedValueType - not 'T' itself
Definition at line 149 of file MultiSet.h.
using Stroika::Foundation::Containers::MultiSet< T, TRAITS >::ElementEqualityComparerType = Common::ComparisonRelationDeclaration<Common::ComparisonRelationType::eEquals, function<bool (ArgByValueType<T>, ArgByValueType<T>)> > |
This is the type returned by GetElementEqualsComparer () and CAN be used as the argument to a MultiSet<> as EqualityComparer, but we allow any template in the Set<> CTOR for an equalityComparer that follows the IEqualsComparer concept.
Definition at line 160 of file MultiSet.h.
Stroika::Foundation::Containers::MultiSet< T, TRAITS >::MultiSet | ( | ) |
All constructors either copy their source comparer (copy/move CTOR), or use the provided argument comparer (which in turn defaults to equal_to<T>).
Definition at line 39 of file MultiSet.inl.
bool Stroika::Foundation::Containers::MultiSet< T, TRAITS >::Contains | ( | ArgByValueType< T > | item | ) | const |
Contains (item) is equivalent to OccurrencesOf (item) != 0, but maybe faster (since it doesn't need to compute the fully tally).
Definition at line 230 of file MultiSet.inl.
void Stroika::Foundation::Containers::MultiSet< T, TRAITS >::Add | ( | ArgByValueType< T > | item | ) |
Definition at line 248 of file MultiSet.inl.
nonvirtual void Stroika::Foundation::Containers::MultiSet< T, TRAITS >::AddAll | ( | ITERATOR_OF_ADDABLE && | start, |
ITERATOR_OF_ADDABLE2 && | end | ||
) |
void Stroika::Foundation::Containers::MultiSet< T, TRAITS >::Remove | ( | ArgByValueType< T > | item, |
CounterType | count = 1 |
||
) |
remove the argument data from the multiset. The data specified MUST exist (require) - else use RemoveIf ()
This function requires that the iterator 'i' came from this container.
The value pointed to by 'i' is removed.
If using the item/count or just item overloads, then MultiSet<> requires that the removed items are present.
nextI | - if provided (not null) - will be filled in with the next value after where iterator i is pointing - since i is invalidated by changing the container) |
Definition at line 292 of file MultiSet.inl.
size_t Stroika::Foundation::Containers::MultiSet< T, TRAITS >::RemoveIf | ( | ArgByValueType< T > | item, |
CounterType | count = 1 |
||
) |
remove the argument data from the multiset (can specify remove of more than are present) - returns number actually removed (multisets never have count < 0)
Definition at line 304 of file MultiSet.inl.
void Stroika::Foundation::Containers::MultiSet< T, TRAITS >::RemoveAll | ( | ) |
RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items.
The no-arg overload removes all (quickly).
The overloads that remove some subset of the items returns the number of items so removed.
Definition at line 235 of file MultiSet.inl.
void Stroika::Foundation::Containers::MultiSet< T, TRAITS >::UpdateCount | ( | const Iterator< value_type > & | i, |
CounterType | newCount, | ||
Iterator< value_type > * | nextI = nullptr |
||
) |
if newCount == 0, equivalent to Remove(i). Require not i.Done () - so it must point to a given item.
On return, nextI, if non-null, will point to the next element after the argument 'i' (useful for iteration).
Definition at line 309 of file MultiSet.inl.
void Stroika::Foundation::Containers::MultiSet< T, TRAITS >::SetCount | ( | ArgByValueType< T > | i, |
CounterType | newCount | ||
) |
It's perfectly legal for i to be missing before or after.
Definition at line 316 of file MultiSet.inl.
auto Stroika::Foundation::Containers::MultiSet< T, TRAITS >::OccurrencesOf | ( | ArgByValueType< T > | item | ) | const |
OccurrencesOf() returns the number of occurrences of 'item' in the tally. The items are compared with operator==.
If there are no copies of item in the MultiSet, 0 is returned.
Definition at line 327 of file MultiSet.inl.
auto Stroika::Foundation::Containers::MultiSet< T, TRAITS >::TotalOccurrences | ( | ) | const |
Returns the sum of all this MultiSets contained elements. This is equivalent to Elements ().size ().
Definition at line 132 of file MultiSet.inl.
auto Stroika::Foundation::Containers::MultiSet< T, TRAITS >::erase | ( | const Iterator< value_type > & | i | ) |
Definition at line 141 of file MultiSet.inl.
void Stroika::Foundation::Containers::MultiSet< T, TRAITS >::clear | ( | ) |
Iterable< T > Stroika::Foundation::Containers::MultiSet< T, TRAITS >::Elements | ( | ) | const |
This is like the MultiSet was a Collection<T> (or plain Iterable<T>). If something is in there N times, it will show up in iteration N times. No guarantee is made as to order of iteration.
Elements () makes no guarantees about whether or not modifications to the underlying MultiSet<> will appear in the Elements() Iterable<T>.
Definition at line 153 of file MultiSet.inl.
Iterable< T > Stroika::Foundation::Containers::MultiSet< T, TRAITS >::UniqueElements | ( | ) | const |
UniqueElements () operates as if it copies the data from the original container, and will not reflect any subsequent changes.
Definition at line 196 of file MultiSet.inl.
Iterable< typename TRAITS::CountedValueType > Stroika::Foundation::Containers::MultiSet< T, TRAITS >::Top | ( | ) | const |
Find the most commonly occurring elements of the multiset (list with count ordered most to last)
\See Iterable<T>::Top \See TopElements
Definition at line 201 of file MultiSet.inl.
Iterable< T > Stroika::Foundation::Containers::MultiSet< T, TRAITS >::TopElements | ( | ) | const |
Find the most commonly occurring elements of the multiset (list of elements - without count - ordered most to last)
\See Iterable<T>::Top \See Top
Definition at line 215 of file MultiSet.inl.
nonvirtual RESULT_CONTAINER Stroika::Foundation::Containers::MultiSet< T, TRAITS >::Where | ( | INCLUDE_PREDICATE && | includeIfTrue | ) | const |
See Iterable<T>::Where - except defaults to MultiSet, and handles cloning rep properties for that special case
auto Stroika::Foundation::Containers::MultiSet< T, TRAITS >::GetElementEqualsComparer | ( | ) | const |
Return the function used to compare if two elements are equal (not to be confused with MultiSet<>::EqualsComparer)
Definition at line 225 of file MultiSet.inl.
bool Stroika::Foundation::Containers::MultiSet< T, TRAITS >::operator== | ( | const MultiSet< T, TRAITS > & | rhs | ) | const |
Definition at line 391 of file MultiSet.inl.
MultiSet< T, TRAITS > & Stroika::Foundation::Containers::MultiSet< T, TRAITS >::operator+= | ( | ArgByValueType< T > | item | ) |
Synonym for Add (), or AddAll() (depending on argument);
Definition at line 360 of file MultiSet.inl.
|
protected |
Utility to get WRITABLE underlying shared_ptr (replacement for what we normally do - _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ()) but where we also handle the cloning/patching of the associated iterator.
When you have a non-const operation (such as Remove) with an argument of an Iterator<>, then due to COW, you may end up cloning the container rep, and yet the Iterator<> contains a pointer to the earlier rep (and so maybe unusable).
Prior to Stroika 2.1b14, this was handled elegantly, and automatically, by the iterator patching mechanism. But that was deprecated (due to cost, and rarity of use), in favor of this more restricted feature, where we just patch the iterators on an as-needed basis.
Definition at line 372 of file MultiSet.inl.