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  } while (result == keyValMap.end() and curKey.has_value());
71 
72  return result;
73  }
74 
75  /**
76  * @brief Get the entry in the map for which the returned key is the longest prefix
77  * of the given key among the keys in the map that satisfy the predicate.
78  *
79  * `prefixFunc` is used to successively calculate the prefixes of the given key.
80  * It must be pure and return an empty optional when there is no shorter
81  * prefix of the given key (for strings, this would be the case when passed the empty string).
82  * `predicate` is used to filter for entries that satisfy the desired condition.
83  * It must be pure.
84  *
85  * @param keyValMap the map that contains the key-value-pairs to search
86  * @param prefixFunc the function that returns the longest non-identical prefix of the key
87  * @param predicate the predicate to filter entries on
88  * @param key the key to calculate the prefixes of
89  *
90  * @return The iterator pointing to the found entry, or `keyValMap.end()`.
91  */
92  template <typename KeyT, typename ValueT>
93  typename std::map<KeyT, ValueT>::const_iterator
95  const std::map<KeyT, ValueT>& keyValMap,
96  const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc,
97  const KeyT& key,
98  const std::function<bool(const KeyT&, const ValueT&)>& predicate)
99  {
100  std::optional<KeyT> curKey = key;
101 
102  typename std::map<KeyT, ValueT>::const_iterator result = keyValMap.end();
103  do
104  {
105  auto iterator = keyValMap.find(curKey.value());
106  if (iterator != keyValMap.end() and predicate(iterator->first, iterator->second))
107  {
108  result = iterator;
109  }
110  else
111  {
112  curKey = prefixFunc(curKey.value());
113  }
114  } while (result == keyValMap.end() and curKey.has_value());
115 
116  return result;
117  }
118 
119  /**
120  * @brief Accumulate all the values in a map for which the keys are prefixes of the given key.
121  *
122  * `AccumulateT` is a type that the values will be accumulated into using `accumulateFunc`.
123  * `accumulateFunc` is a function that modifies the given accumulator
124  * (by, e.g., adding the given value to it).
125  *
126  * The values are accumulated in order from the longest key to the shortest.
127  *
128  * @see `getWithLongestPrefix` for a description of `prefixFunc`
129  * @param keyValMap the map that contains the key-value-pairs to search
130  * @param prefixFunc the function that returns the longest non-identical prefix of the key
131  * @param accumulateFunc the function that accumulates the values in the accumulator
132  * @param key the key to calculate the prefixes of
133  */
134  template <typename KeyT, typename ValueT, typename AccumulateT>
135  AccumulateT
137  const std::map<KeyT, ValueT>& keyValMap,
138  const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
139  const std::function<void(AccumulateT&, const ValueT&)> accumulateFunc,
140  const KeyT& key)
141  {
142  std::optional<KeyT> curKey = key;
143  AccumulateT values;
144  do
145  {
146  const auto nextEntry =
147  findEntryWithLongestPrefix<KeyT, ValueT>(keyValMap, prefixFunc, curKey.value());
148  if (nextEntry != keyValMap.end())
149  {
150  curKey = prefixFunc(nextEntry->first);
151  accumulateFunc(values, nextEntry->second);
152  }
153  else
154  {
155  curKey.reset();
156  }
157  } while (curKey.has_value());
158 
159  return values;
160  }
161 
162  /**
163  * @brief Collect all the values in a map for which the keys are prefixes of the given key.
164  *
165  * This is a specialization of the general `accumulateFromPrefixes`
166  * for collecting single values into a vector.
167  *
168  * @see `accumulateFromPrefixes` for a detailed description
169  * @param keyValMap the map that contains the key-value-pairs to search
170  * @param prefixFunc the function that returns the longest non-identical prefix of the key
171  * @param key the key to calculate the prefixes of
172  */
173  template <typename KeyT, typename ValueT>
174  std::vector<ValueT>
175  accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap,
176  const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
177  const KeyT& key)
178  {
179  return accumulateFromPrefixes<KeyT, ValueT, std::vector<ValueT>>(
180  keyValMap,
181  prefixFunc,
182  [](std::vector<ValueT>& values, const ValueT& val) { values.push_back(val); },
183  key);
184  }
185 
186  /**
187  * @brief Collect all the values in a map for which the keys are prefixes of the given key.
188  *
189  * This is a specialization of the general `accumulateFromPrefixes`
190  * for appending vector values into a single vector.
191  *
192  * @see `accumulateFromPrefixes` for a detailed description
193  * @param keyValMap the map that contains the key-value-pairs to search
194  * @param prefixFunc the function that returns the longest non-identical prefix of the key
195  * @param key the key to calculate the prefixes of
196  */
197  template <typename KeyT, typename ValueT>
198  std::vector<ValueT>
199  accumulateFromPrefixes(const std::map<KeyT, std::vector<ValueT>>& keyValMap,
200  const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
201  const KeyT& key)
202  {
203  return accumulateFromPrefixes<KeyT, std::vector<ValueT>, std::vector<ValueT>>(
204  keyValMap,
205  prefixFunc,
206  [](std::vector<ValueT>& values, const std::vector<ValueT>& val)
207  { values.insert(values.end(), val.begin(), val.end()); },
208  key);
209  }
210 
211  } // namespace detail
212 
213  std::optional<MemoryID> inline getMemoryIDParent(const MemoryID& memID)
214  {
215  if (!memID.hasMemoryName())
216  {
217  return std::nullopt;
218  }
219  MemoryID parent = memID.removeLeafItem();
220  return {parent};
221  }
222 
223  /**
224  * @brief Find the entry with the most specific key that contains the given ID,
225  * or `idMap.end()` if no key contains the ID.
226  *
227  * @see `detail::findEntryWithLongestPrefix()`
228  */
229  template <typename ValueT>
230  typename std::map<MemoryID, ValueT>::const_iterator
231  findMostSpecificEntryContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
232  {
233  return detail::findEntryWithLongestPrefix<MemoryID, ValueT>(idMap, &getMemoryIDParent, id);
234  }
235 
236  /**
237  * @brief Find the entry with the most specific key that contains the given ID
238  * and satisfies the predicate, or `idMap.end()` if no key contains the ID and satisfies
239  * the predicate.
240  *
241  * @see `detail::findEntryWithLongestPrefixAnd()`
242  */
243  template <typename ValueT>
244  typename std::map<MemoryID, ValueT>::const_iterator
246  const std::map<MemoryID, ValueT>& idMap,
247  const MemoryID& id,
248  const std::function<bool(const MemoryID&, const ValueT&)>& predicate)
249  {
250  return detail::findEntryWithLongestPrefixAnd<MemoryID, ValueT>(
251  idMap, &getMemoryIDParent, id, predicate);
252  }
253 
254  /**
255  * @brief Return all values of keys containing the given ID.
256  *
257  * @see `detail::accumulateFromPrefixes()`
258  */
259  template <typename ValueT>
260  std::vector<ValueT>
261  accumulateEntriesContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
262  {
263  return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, id);
264  }
265 
266  /**
267  * @brief Return all values of keys containing the given ID in a flattened vector.
268  *
269  * @see `detail::accumulateFromPrefixes()`
270  */
271  template <typename ValueT>
272  std::vector<ValueT>
273  accumulateEntriesContainingID(const std::map<MemoryID, std::vector<ValueT>>& idMap,
274  const MemoryID& key)
275  {
276  return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, key);
277  }
278 
279 
280 } // namespace armarx::armem
armarx::armem::MemoryID::removeLeafItem
MemoryID removeLeafItem() const
Definition: MemoryID.cpp:334
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:261
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:136
MemoryID.h
armarx::armem
Definition: LegacyRobotStateMemoryAdapter.cpp:32
ProsthesisInterface.values
values
Definition: ProsthesisInterface.py:190
detail
Definition: OpenCVUtil.cpp:128
armarx::armem::getMemoryIDParent
std::optional< MemoryID > getMemoryIDParent(const MemoryID &memID)
Definition: container_maps.h:213
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:94
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:231
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:245