HiPipe  0.7.0
C++17 data pipeline with Python bindings.
index_mapper.hpp
1 /****************************************************************************
2  * hipipe library
3  * Copyright (c) 2017, Cognexa Solutions s.r.o.
4  * Copyright (c) 2018, Iterait a.s.
5  * Author(s) Filip Matzner
6  *
7  * This file is distributed under the MIT License.
8  * See the accompanying file LICENSE.txt for the complete license agreement.
9  ****************************************************************************/
11 
12 #ifndef HIPIPE_CORE_INDEX_MAPPER_HPP
13 #define HIPIPE_CORE_INDEX_MAPPER_HPP
14 
15 #include <range/v3/range/conversion.hpp>
16 #include <range/v3/view/transform.hpp>
17 
18 #include <unordered_map>
19 #include <vector>
20 
21 namespace hipipe {
22 
23 namespace rgv = ranges::views;
24 
27 template<typename T>
28 class index_mapper {
29 public:
30  index_mapper() = default;
31 
35  template<typename Rng>
36  index_mapper(Rng&& values)
37  {
38  insert(std::forward<Rng>(values));
39  }
40 
42  index_mapper(std::initializer_list<T> values)
43  {
44  insert(rgv::all(values));
45  }
46 
47  // index_for //
48 
51  std::size_t index_for(const T& val) const
52  {
53  if (!contains(val)) {
54  throw std::out_of_range{"The index_mapper does not contain the given value."};
55  }
56  return val2idx_.at(val);
57  }
58 
60  std::size_t index_for(const T& val, std::size_t defval) const
61  {
62  auto pos = val2idx_.find(val);
63  if (pos == val2idx_.end()) return defval;
64  return pos->second;
65  }
66 
69  std::vector<std::size_t> index_for(const std::vector<T>& vals) const
70  {
71  return ranges::to_vector(rgv::transform(
72  vals, [this](const T& val) {
73  return this->index_for(val);
74  }));
75  }
76 
78  std::vector<std::size_t> index_for(const std::vector<T>& vals, std::size_t defval) const
79  {
80  return ranges::to_vector(rgv::transform(
81  vals, [this, defval](const T& val) {
82  return this->index_for(val, defval);
83  }));
84  }
85 
86  // at //
87 
90  const T& at(const std::size_t& idx) const
91  {
92  if (idx >= size()) {
93  throw std::out_of_range{"Index " + std::to_string(idx) + " cannot be found in "
94  "index_mapper of size " + std::to_string(size()) + "."};
95  }
96  return idx2val_[idx];
97  }
98 
99 
102  std::vector<T> at(const std::vector<std::size_t>& idxs) const
103  {
104  return ranges::to_vector(rgv::transform(
105  idxs, [this](std::size_t idx) {
106  return this->at(idx);
107  }));
108  }
109 
110  // insert //
111 
116  std::size_t insert(T val)
117  {
118  if (contains(val)) {
119  throw std::invalid_argument{"The element is already present in the index mapper."};
120  }
121  val2idx_[val] = idx2val_.size();
122  idx2val_.push_back(std::move(val));
123  return idx2val_.size() - 1;
124  }
125 
132  CPP_template(class Rng)(requires ranges::container<Rng>)
133  void insert(Rng rng)
134  {
135  for (auto& val : rng) insert(std::move(val));
136  }
137 
139  CPP_template(class Rng)(requires ranges::view_<Rng>)
140  void insert(Rng rng)
141  {
142  for (auto&& val : rng) insert(std::forward<decltype(val)>(val));
143  }
144 
145  // try_insert //
146 
152  bool try_insert(T val)
153  {
154  if (contains(val)) return false;
155  insert(std::move(val));
156  return true;
157  }
158 
162  CPP_template(class Rng)(requires ranges::container<Rng>)
163  void try_insert(Rng rng)
164  {
165  for (auto& val : rng) try_insert(std::move(val));
166  }
167 
169  CPP_template(class Rng)(requires ranges::view_<Rng>)
170  void try_insert(Rng rng)
171  {
172  for (auto&& val : rng) try_insert(std::forward<decltype(val)>(val));
173  }
174 
175  // helper functions //
176 
178  bool contains(const T& val) const
179  {
180  return val2idx_.count(val);
181  }
182 
184  std::size_t size() const
185  {
186  return val2idx_.size();
187  }
188 
189  // data access //
190 
192  const std::vector<T>& values() const
193  {
194  return idx2val_;
195  }
196 
197 private:
198  std::unordered_map<T, std::size_t> val2idx_;
199  std::vector<T> idx2val_;
200 };
201 
214 template<typename Rng, typename T = ranges::range_value_t<Rng>>
216 {
217  index_mapper<T> mapper;
218  mapper.try_insert(std::forward<Rng>(rng));
219  return mapper;
220 }
221 
222 } // end namespace hipipe
223 #endif
hipipe::utility::to_string
std::string to_string(const T &value)
Convert the given type to std::string.
Definition: string.hpp:90
hipipe::make_unique_index_mapper
index_mapper< T > make_unique_index_mapper(Rng &&rng)
Make index mapper from unique elements of a range.
Definition: index_mapper.hpp:214
hipipe::index_mapper::values
const std::vector< T > & values() const
Returns all the contained values.
Definition: index_mapper.hpp:191
hipipe::index_mapper
Provides a bidirectional access from values to their indices in an std::vector.
Definition: index_mapper.hpp:27
hipipe::index_mapper::size
std::size_t size() const
Returns the size of the mapper.
Definition: index_mapper.hpp:183
hipipe::index_mapper::CPP_template
CPP_template(class Rng)(requires ranges
Definition: index_mapper.hpp:131
hipipe::index_mapper::at
const T & at(const std::size_t &idx) const
Definition: index_mapper.hpp:89
hipipe::index_mapper::try_insert
bool try_insert(T val)
Definition: index_mapper.hpp:151
hipipe::index_mapper::contains
bool contains(const T &val) const
Checks whether the mapper contains the given value.
Definition: index_mapper.hpp:177
hipipe::stream::transform
auto transform(from_t< FromColumns... > f, to_t< ToColumns... > t, Fun fun, dim_t< Dim > d=dim_t< 1 >{})
Transform a subset of hipipe columns to a different subset of hipipe columns.
Definition: transform.hpp:218
hipipe::index_mapper::index_for
std::size_t index_for(const T &val) const
Definition: index_mapper.hpp:50
hipipe::index_mapper::insert
std::size_t insert(T val)
Definition: index_mapper.hpp:115