All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MakeIndex.h
Go to the documentation of this file.
1 /**
2  * @file MakeIndex.h
3  * @brief Procedures to create maps of object locations
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date March 13th, 2015
6  */
7 
8 #ifndef LARDATA_UTILITIES_MAKEINDEX_H
9 #define LARDATA_UTILITIES_MAKEINDEX_H
10 
11 namespace util {
12 
13  /**
14  * @brief Creates a map of indices from an existing collection
15  * @tparam Coll type of the collection
16  * @tparam KeyOf type of the extractor of the key
17  * @param data the data collection
18  * @param key_of instance of a functor extracting a key value from a datum
19  * @return a vector with indices corresponding to the data keys
20  *
21  * This function maps the index of the items in data to an integral key
22  * extracted from each item.
23  * For example, if the items are wires and the key_of function extracts their
24  * channel ID, the resulting vector will contain for each channel ID
25  * the index in data of the wire with that channel ID.
26  *
27  * The key is converted into a unsigned integer (`size_t`).
28  * If multiple items have the same key, the outcome for that key is undefined.
29  * If no items has a specific key, the index of that key is assigned as
30  * @code std::numeric_limits<size_t>::max() @endcode, i.e. an index larger
31  * than the size of the original data collection.
32  *
33  * The returned vector is big enough to accommodate indices corresponding to
34  * the keys of all the items in data. It may contain "holes" (that is, some
35  * keys that have no corresponding items have a
36  * @code std::numeric_limits<size_t>::max() @endcode value).
37  * The memory allocated for the vector may be larger than necessary (if that
38  * is a problem, `std::vector::shrink_to_fit()` can be used, but it may create
39  * more problems than it solves).
40  *
41  */
42  template <typename Coll, typename KeyOf>
43  std::vector<size_t> MakeIndex(Coll const& data, KeyOf key_of = KeyOf()) {
44 
45  // we start the index with the best guess that all the items will have
46  // a unique key and they are contiguous:
47  // the index would have the same size as the data
48  std::vector<size_t> Index(data.size(), std::numeric_limits<size_t>::max());
49 
50  size_t min_size = 0; // minimum size needed to hold all keys
51 
52  size_t iDatum = 0;
53  for (auto const& datum: data) {
54  size_t key = size_t(key_of(datum));
55  if (key >= min_size) min_size = key + 1;
56  if (Index.size() <= key) {
57  // make room for the entry: double the size
58  Index.resize(
59  std::max(key + 1, Index.size() * 2),
60  std::numeric_limits<size_t>::max()
61  );
62  } // if expand index
63  Index[key] = iDatum;
64  ++iDatum;
65  } // for datum
66  Index.resize(min_size);
67  return Index;
68  } // MakeIndex()
69 
70 
71  /**
72  * @brief Creates a map of objects from an existing collection
73  * @tparam Coll type of the collection
74  * @tparam KeyOf type of the extractor of the key
75  * @param data the data collection
76  * @param key_of instance of a functor extracting a key value from a datum
77  * @return a vector with pointers to data corresponding to their keys
78  *
79  * This function maps the items in data to an integral key extracted from each
80  * of them.
81  * For example, if the items are wires and the key_of function extracts their
82  * channel ID, the resulting vector will contain for each channel ID
83  * the pointer to the wire with that channel ID.
84  *
85  * The key is converted into a unsigned integer (`size_t`).
86  * If multiple items have the same key, the outcome for that key is undefined.
87  * If no items has a specific key, the index of that key is assigned a
88  * null pointer.
89  *
90  * The returned vector is big enough to accommodate pointers corresponding to
91  * the keys of all the items in data. It may contain "holes" (that is, some
92  * keys that have no corresponding items have a null pointer value).
93  * The memory allocated for the vector may be larger than necessary (if that
94  * is a problem, `std::vector::shrink_to_fit()` can be used, but it may create
95  * more problems than it solves).
96  *
97  */
98  template <typename Coll, typename KeyOf>
99  auto MakeMap(Coll const& data, KeyOf key_of = KeyOf())
100  -> std::vector<decltype(key_of(*(data.begin()))) const*>
101  {
102  using Mapped_t = decltype(key_of(*(data.begin())));
103  using Ptr_t = Mapped_t const*;
104  using Map_t = std::vector<Ptr_t>;
105 
106  // we start the index with the best guess that all the items will have
107  // a unique key and they are contiguous:
108  // the index would have the same size as the data
109  Map_t Index(data.size(), nullptr);
110 
111  size_t min_size = 0; // minimum size needed to hold all keys
112 
113  for (auto const& datum: data) {
114  size_t key = size_t(key_of(datum));
115  if (key >= min_size) min_size = key + 1;
116  if (Index.size() <= key) {
117  // make room for the entry: double the size
118  Index.resize(std::max(key + 1, Index.size() * 2), nullptr);
119  } // if expand index
120  Index[key] = &datum;
121  } // for datum
122  Index.resize(min_size);
123  return Index;
124  } // MakeMap()
125 
126 } // namespace util
127 
128 
129 #endif // LARDATA_UTILITIES_MAKEINDEX_H
std::vector< size_t > MakeIndex(Coll const &data, KeyOf key_of=KeyOf())
Creates a map of indices from an existing collection.
Definition: MakeIndex.h:43
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
auto MakeMap(Coll const &data, KeyOf key_of=KeyOf()) -> std::vector< decltype(key_of(*(data.begin()))) const * >
Creates a map of objects from an existing collection.
Definition: MakeIndex.h:99