container_maps.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @author phesch ( ulila at student dot kit dot edu )
17  * @date 2022
18  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19  * GNU General Public License
20  */
21 
22 #pragma once
23 
24 #include <map>
25 #include <optional>
26 #include <tuple>
27 
29 
30 namespace armarx::armem
31 {
32 
33  namespace detail
34  {
35 
36  /**
37  * @brief Get the entry in the map for which the returned key is the longest prefix
38  * of the given key among the keys in the map.
39  *
40  * `prefixFunc` is used to successively calculate the prefixes of the given key.
41  * It must be pure and return an empty optional when there is no shorter
42  * prefix of the given key (for strings, this would be the case when passed the empty string).
43  *
44  * @param keyValMap the map that contains the key-value-pairs to search
45  * @param prefixFunc the function that returns the longest non-identical prefix of the key
46  * @param key the key to calculate the prefixes of
47  *
48  * @return The iterator pointing to the found entry, or `keyValMap.end()`.
49  */
50  template <typename KeyT, typename ValueT>
51  typename std::map<KeyT, ValueT>::const_iterator
52  findEntryWithLongestPrefix(const std::map<KeyT, ValueT>& keyValMap,
53  const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc,
54  const KeyT& key)
55  {
56  std::optional<KeyT> curKey = key;
57 
58  typename std::map<KeyT, ValueT>::const_iterator result = keyValMap.end();
59  do
60  {
61  auto iterator = keyValMap.find(curKey.value());
62  if (iterator != keyValMap.end())
63  {
64  result = iterator;
65  }
66  else
67  {
68  curKey = prefixFunc(curKey.value());
69  }
70  }
71  while (result == keyValMap.end() and curKey.has_value());
72 
73  return result;
74  }
75 
76  /**
77  * @brief Get the entry in the map for which the returned key is the longest prefix
78  * of the given key among the keys in the map that satisfy the predicate.
79  *
80  * `prefixFunc` is used to successively calculate the prefixes of the given key.
81  * It must be pure and return an empty optional when there is no shorter
82  * prefix of the given key (for strings, this would be the case when passed the empty string).
83  * `predicate` is used to filter for entries that satisfy the desired condition.
84  * It must be pure.
85  *
86  * @param keyValMap the map that contains the key-value-pairs to search
87  * @param prefixFunc the function that returns the longest non-identical prefix of the key
88  * @param predicate the predicate to filter entries on
89  * @param key the key to calculate the prefixes of
90  *
91  * @return The iterator pointing to the found entry, or `keyValMap.end()`.
92  */
93  template <typename KeyT, typename ValueT>
94  typename std::map<KeyT, ValueT>::const_iterator
96  const std::map<KeyT, ValueT>& keyValMap,
97  const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc,
98  const KeyT& key,
99  const std::function<bool(const KeyT&, const ValueT&)>& predicate)
100  {
101  std::optional<KeyT> curKey = key;
102 
103  typename std::map<KeyT, ValueT>::const_iterator result = keyValMap.end();
104  do
105  {
106  auto iterator = keyValMap.find(curKey.value());
107  if (iterator != keyValMap.end() and predicate(iterator->first, iterator->second))
108  {
109  result = iterator;
110  }
111  else
112  {
113  curKey = prefixFunc(curKey.value());
114  }
115  }
116  while (result == keyValMap.end() and curKey.has_value());
117 
118  return result;
119  }
120 
121  /**
122  * @brief Accumulate all the values in a map for which the keys are prefixes of the given key.
123  *
124  * `AccumulateT` is a type that the values will be accumulated into using `accumulateFunc`.
125  * `accumulateFunc` is a function that modifies the given accumulator
126  * (by, e.g., adding the given value to it).
127  *
128  * The values are accumulated in order from the longest key to the shortest.
129  *
130  * @see `getWithLongestPrefix` for a description of `prefixFunc`
131  * @param keyValMap the map that contains the key-value-pairs to search
132  * @param prefixFunc the function that returns the longest non-identical prefix of the key
133  * @param accumulateFunc the function that accumulates the values in the accumulator
134  * @param key the key to calculate the prefixes of
135  */
136  template <typename KeyT, typename ValueT, typename AccumulateT>
137  AccumulateT
138  accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap,
139  const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
140  const std::function<void(AccumulateT&, const ValueT&)> accumulateFunc,
141  const KeyT& key)
142  {
143  std::optional<KeyT> curKey = key;
144  AccumulateT values;
145  do
146  {
147  const auto nextEntry =
148  findEntryWithLongestPrefix<KeyT, ValueT>(keyValMap, prefixFunc, curKey.value());
149  if (nextEntry != keyValMap.end())
150  {
151  curKey = prefixFunc(nextEntry->first);
152  accumulateFunc(values, nextEntry->second);
153  }
154  else
155  {
156  curKey.reset();
157  }
158  }
159  while (curKey.has_value());
160 
161  return values;
162  }
163 
164  /**
165  * @brief Collect all the values in a map for which the keys are prefixes of the given key.
166  *
167  * This is a specialization of the general `accumulateFromPrefixes`
168  * for collecting single values into a vector.
169  *
170  * @see `accumulateFromPrefixes` for a detailed description
171  * @param keyValMap the map that contains the key-value-pairs to search
172  * @param prefixFunc the function that returns the longest non-identical prefix of the key
173  * @param key the key to calculate the prefixes of
174  */
175  template <typename KeyT, typename ValueT>
176  std::vector<ValueT>
177  accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap,
178  const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
179  const KeyT& key)
180  {
181  return accumulateFromPrefixes<KeyT, ValueT, std::vector<ValueT>>(
182  keyValMap,
183  prefixFunc,
184  [](std::vector<ValueT>& values, const ValueT& val) { values.push_back(val); },
185  key);
186  }
187 
188  /**
189  * @brief Collect all the values in a map for which the keys are prefixes of the given key.
190  *
191  * This is a specialization of the general `accumulateFromPrefixes`
192  * for appending vector values into a single vector.
193  *
194  * @see `accumulateFromPrefixes` for a detailed description
195  * @param keyValMap the map that contains the key-value-pairs to search
196  * @param prefixFunc the function that returns the longest non-identical prefix of the key
197  * @param key the key to calculate the prefixes of
198  */
199  template <typename KeyT, typename ValueT>
200  std::vector<ValueT>
201  accumulateFromPrefixes(const std::map<KeyT, std::vector<ValueT>>& keyValMap,
202  const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
203  const KeyT& key)
204  {
205  return accumulateFromPrefixes<KeyT, std::vector<ValueT>, std::vector<ValueT>>(
206  keyValMap,
207  prefixFunc,
208  [](std::vector<ValueT>& values, const std::vector<ValueT>& val)
209  { values.insert(values.end(), val.begin(), val.end()); },
210  key);
211  }
212 
213  } // namespace detail
214 
215 
216  std::optional<MemoryID> inline getMemoryIDParent(const MemoryID& memID)
217  {
218  if (!memID.hasMemoryName())
219  {
220  return std::nullopt;
221  }
222  MemoryID parent = memID.removeLeafItem();
223  return {parent};
224  }
225 
226 
227  /**
228  * @brief Find the entry with the most specific key that contains the given ID,
229  * or `idMap.end()` if no key contains the ID.
230  *
231  * @see `detail::findEntryWithLongestPrefix()`
232  */
233  template <typename ValueT>
234  typename std::map<MemoryID, ValueT>::const_iterator
235  findMostSpecificEntryContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
236  {
237  return detail::findEntryWithLongestPrefix<MemoryID, ValueT>(idMap, &getMemoryIDParent, id);
238  }
239 
240 
241  /**
242  * @brief Find the entry with the most specific key that contains the given ID
243  * and satisfies the predicate, or `idMap.end()` if no key contains the ID and satisfies
244  * the predicate.
245  *
246  * @see `detail::findEntryWithLongestPrefixAnd()`
247  */
248  template <typename ValueT>
249  typename std::map<MemoryID, ValueT>::const_iterator
250  findMostSpecificEntryContainingIDAnd(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id,
251  const std::function<bool(const MemoryID&, const ValueT&)>& predicate)
252  {
253  return detail::findEntryWithLongestPrefixAnd<MemoryID, ValueT>(
254  idMap, &getMemoryIDParent, id, predicate);
255  }
256 
257 
258  /**
259  * @brief Return all values of keys containing the given ID.
260  *
261  * @see `detail::accumulateFromPrefixes()`
262  */
263  template <typename ValueT>
264  std::vector<ValueT>
265  accumulateEntriesContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
266  {
267  return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, id);
268  }
269 
270 
271  /**
272  * @brief Return all values of keys containing the given ID in a flattened vector.
273  *
274  * @see `detail::accumulateFromPrefixes()`
275  */
276  template <typename ValueT>
277  std::vector<ValueT>
278  accumulateEntriesContainingID(const std::map<MemoryID, std::vector<ValueT>>& idMap,
279  const MemoryID& key)
280  {
281  return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, key);
282  }
283 
284 
285 } // namespace armarx::armem
armarx::armem::MemoryID::removeLeafItem
MemoryID removeLeafItem() const
Definition: MemoryID.cpp:329
armarx::armem::accumulateEntriesContainingID
std::vector< ValueT > accumulateEntriesContainingID(const std::map< MemoryID, ValueT > &idMap, const MemoryID &id)
Return all values of keys containing the given ID.
Definition: container_maps.h:265
armarx::armem::detail::accumulateFromPrefixes
AccumulateT accumulateFromPrefixes(const std::map< KeyT, ValueT > &keyValMap, const std::function< std::optional< KeyT >(const KeyT &)> &prefixFunc, const std::function< void(AccumulateT &, const ValueT &)> accumulateFunc, const KeyT &key)
Accumulate all the values in a map for which the keys are prefixes of the given key.
Definition: container_maps.h:138
MemoryID.h
armarx::armem
Definition: LegacyRobotStateMemoryAdapter.cpp:31
ProsthesisInterface.values
values
Definition: ProsthesisInterface.py:190
detail
Definition: OpenCVUtil.cpp:127
armarx::armem::getMemoryIDParent
std::optional< MemoryID > getMemoryIDParent(const MemoryID &memID)
Definition: container_maps.h:216
armarx::armem::detail::findEntryWithLongestPrefixAnd
std::map< KeyT, ValueT >::const_iterator findEntryWithLongestPrefixAnd(const std::map< KeyT, ValueT > &keyValMap, const std::function< std::optional< KeyT >(KeyT &)> &prefixFunc, const KeyT &key, const std::function< bool(const KeyT &, const ValueT &)> &predicate)
Get the entry in the map for which the returned key is the longest prefix of the given key among the ...
Definition: container_maps.h:95
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::armem::detail::findEntryWithLongestPrefix
std::map< KeyT, ValueT >::const_iterator findEntryWithLongestPrefix(const std::map< KeyT, ValueT > &keyValMap, const std::function< std::optional< KeyT >(KeyT &)> &prefixFunc, const KeyT &key)
Get the entry in the map for which the returned key is the longest prefix of the given key among the ...
Definition: container_maps.h:52
armarx::armem::MemoryID::hasMemoryName
bool hasMemoryName() const
Definition: MemoryID.h:103
armarx::armem::findMostSpecificEntryContainingID
std::map< MemoryID, ValueT >::const_iterator findMostSpecificEntryContainingID(const std::map< MemoryID, ValueT > &idMap, const MemoryID &id)
Find the entry with the most specific key that contains the given ID, or idMap.end() if no key contai...
Definition: container_maps.h:235
armarx::armem::findMostSpecificEntryContainingIDAnd
std::map< MemoryID, ValueT >::const_iterator findMostSpecificEntryContainingIDAnd(const std::map< MemoryID, ValueT > &idMap, const MemoryID &id, const std::function< bool(const MemoryID &, const ValueT &)> &predicate)
Find the entry with the most specific key that contains the given ID and satisfies the predicate,...
Definition: container_maps.h:250