2 Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
5 namespace DerivationFramework { namespace TriggerMatchingUtils {
8 bool insertIntoSortedVector(std::vector<T>& vec, const T& ele)
10 auto itr = std::lower_bound(vec.begin(), vec.end(), ele);
11 // if no lower bound is found or the found element doesn't equal ele then
12 // insert ele at this point
13 if (itr == vec.end() || *itr != ele) {
22 std::vector<typename T::value_type> sorted(T begin, T end)
24 std::vector<typename T::value_type> output(begin, end);
25 std::sort(output.begin(), output.end() );
31 std::vector<std::vector<T>> getAllDistinctCombinations(
32 std::vector<RangedItr<typename std::vector<T>::const_iterator>>& inputs)
34 // This is where the output will go
35 std::vector<std::vector<T>> output;
37 // If inputs is empty or if any of the ranges within inputs are empty then
38 // no combinations will be found!
39 if (inputs.empty() || std::any_of(inputs.begin(), inputs.end(),
40 [] (const auto& rangedItr) { return rangedItr.exhausted(); }) )
43 // This is the current output combination being built
44 std::vector<T> currentCombination;
46 // This iterator points to where in the vector of ranged iterators we are
47 // looking. This can therefore often be acting as an iterator to and
48 // iterator! *itr is an iterator, **itr is a const T&!
49 // To disambiguate I will refer to itr as the outer iterator and *itr as the
51 auto itr = inputs.begin();
53 // Have we exhausted our current inner iterator?
54 if (itr == inputs.end() || itr->exhausted() ) {
55 // If the outer iterator has returned to the beginning then we're done
56 // and every combination has been checked.
57 if (itr == inputs.begin() )
59 // otherwise we need to continue. To do this we
60 // - reset the current inner iterator. This is so that the next time we
61 // return to it we look through all the elements again
62 // - step the outer iterator back
63 // - remove the last element of the current combination. That
64 // element will be replaced by the next valid one from the list *now*
65 // pointed to by the outer iterator.
66 if (itr != inputs.end() )
69 currentCombination.pop_back();
70 } //> end if inner iterator is exhausted
72 // Check if the pointed-to element is already in the current combination
73 const T& currentCandidate = **itr;
74 // Now that we've accessed this value, step past it
77 currentCombination.begin(),
78 currentCombination.end(),
79 currentCandidate) == currentCombination.end() ) {
80 // If it isn't, then add it.
81 currentCombination.push_back(currentCandidate);
82 // Step the outer iterator forwards so we're looking at the next list
84 if (itr == inputs.end() ) {
85 // If we're at the end then this is a complete combination, add it
87 insertIntoSortedVector(output, sorted(
88 currentCombination.begin(),
89 currentCombination.end() ) );
91 } //> end if currentCandidate is in currentCombination
92 } //> end else (if inner iterator is exhausted)
95 } //> end function getAllDistinctCombinations
97 }} //> end namespace DerivationFramework::TriggerMatchingUtils