Turi Create  4.0
stl_util.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 // Probabilistic Reasoning Library (PRL)
7 // Copyright 2009 (see AUTHORS.txt for a list of contributors)
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 
23 #ifndef TURI_STL_UTIL_HPP
24 #define TURI_STL_UTIL_HPP
25 
26 
27 #include <set>
28 #include <map>
29 #include <vector>
30 #include <algorithm>
31 #include <iterator>
32 #include <sstream>
33 #include <iostream>
34 #include <iomanip>
35 #include <core/logging/assertions.hpp>
36 #include <boost/exception/detail/is_output_streamable.hpp>
37 
38 // #include <core/storage/serialization/serialize.hpp>
39 // #include <core/storage/serialization/set.hpp>
40 // #include <core/storage/serialization/map.hpp>
41 
42 namespace turi {
43 
44  /**
45  * \ingroup util
46  * \addtogroup set_and_map Set And Map Utilities
47  * \brief Some mathematical Set and Map routines.
48  * \{
49  */
50  // Functions on sets
51  //============================================================================
52 
53  /**
54  * computes the union of two sets.
55  */
56  template <typename T>
57  std::set<T> set_union(const std::set<T>& a, const std::set<T>& b) {
58  std::set<T> output;
59  std::set_union(a.begin(), a.end(),
60  b.begin(), b.end(),
61  std::inserter(output, output.begin()));
62  return output;
63  }
64 
65  /**
66  * computes the union of a set and a value.
67  */
68  template <typename T>
69  std::set<T> set_union(const std::set<T>& a, const T& b) {
70  std::set<T> output = a;
71  output.insert(b);
72  return output;
73  }
74 
75  /**
76  * computes the intersect of two sets.
77  */
78  template <typename T>
79  std::set<T> set_intersect(const std::set<T>& a, const std::set<T>& b) {
80  std::set<T> output;
81  std::set_intersection(a.begin(), a.end(),
82  b.begin(), b.end(),
83  std::inserter(output, output.begin()));
84  return output;
85  }
86 
87  /**
88  * computes the difference of two sets.
89  */
90  template <typename T>
91  std::set<T> set_difference(const std::set<T>& a, const std::set<T>& b) {
92  std::set<T> output;
93  std::set_difference(a.begin(), a.end(),
94  b.begin(), b.end(),
95  std::inserter(output, output.begin()));
96  return output;
97  }
98 
99 
100  /**
101  * Subtract a value from a set
102  */
103  template <typename T>
104  std::set<T> set_difference(const std::set<T>& a, const T& b) {
105  std::set<T> output = a;
106  output.erase(b);
107  return output;
108  }
109 
110  /**
111  * Partitions a set with a different set.
112  * Returns 2 sets: <s in partition, s not in partition>
113  */
114  template <typename T>
115  std::pair<std::set<T>,std::set<T> >
116  set_partition(const std::set<T>& s, const std::set<T>& partition) {
117  std::set<T> a, b;
118  a = set_intersect(s, partition);
119  b = set_difference(s, partition);
120  return std::make_pair(a, b);
121  }
122 
123  /**
124  * Returns true if the two sets are disjoint
125  */
126  template <typename T>
127  bool set_disjoint(const std::set<T>& a, const std::set<T>& b) {
128  return (intersection_size(a,b) == 0);
129  }
130 
131  /**
132  * Returns true if the two sets are equal
133  */
134  template <typename T>
135  bool set_equal(const std::set<T>& a, const std::set<T>& b) {
136  if (a.size() != b.size()) return false;
137  return a == b; // defined in <set>
138  }
139 
140  /**
141  * Returns true if b is included in a
142  */
143  template <typename T>
144  bool includes(const std::set<T>& a, const std::set<T>& b) {
145  return std::includes(a.begin(), a.end(), b.begin(), b.end());
146  }
147 
148  /**
149  * Returns true if $a \subseteq b$
150  */
151  template <typename T>
152  bool is_subset(const std::set<T>& a, const std::set<T>& b) {
153  return includes(b, a);
154  }
155 
156  /**
157  * Returns true if $b \subseteq a$
158  */
159  template <typename T>
160  bool is_superset(const std::set<T>& a,const std::set<T>& b) {
161  return includes(a, b);
162  }
163 
164  /*
165  * \internal
166  * Prints a container.
167  */
168  template <typename Container>
169  std::ostream& print_range(std::ostream& out, const Container& c,
170  const std::string& left, const std::string& sep,const std::string& right) {
171 
172  out << left;
173 
174  for(auto it = c.begin();;) {
175  if(it == c.end())
176  break;
177 
178  out << *it;
179 
180  ++it;
181 
182  if(it != c.end())
183  out << sep;
184  }
185  out << right << std::endl;
186 
187  return out;
188  }
189 
190 
191  /**
192  * Writes a human representation of the set to the supplied stream.
193  */
194  template <typename T>
195  typename boost::enable_if_c<boost::is_output_streamable<T>::value,
196  std::ostream&>::type
197  operator<<(std::ostream& out, const std::set<T>& s) {
198  return print_range(out, s, "{", ", ", "}");
199  }
200 
201  /**
202  * Writes a human representation of a vector to the supplied stream.
203  */
204  template <typename T>
205  typename boost::enable_if_c<boost::is_output_streamable<T>::value,
206  std::ostream&>::type
207  operator<<(std::ostream& out, const std::vector<T>& v) {
208  return print_range(out, v, "[", ", ", "]");
209  }
210 
211 
212  // Functions on maps
213  //============================================================================
214 
215  /**
216  * constant lookup in a map. assertion failure of key not found in map
217  */
218  template <typename Key, typename T>
219  const T& safe_get(const std::map<Key, T>& map,
220  const Key& key) {
221  typedef typename std::map<Key, T>::const_iterator iterator;
222  iterator iter = map.find(key);
223  ASSERT_TRUE(iter != map.end());
224  return iter->second;
225  } // end of safe_get
226 
227  /**
228  * constant lookup in a map. If key is not found in map,
229  * 'default_value' is returned. Note that this can't return a reference
230  * and must return a copy
231  */
232  template <typename Key, typename T>
233  const T safe_get(const std::map<Key, T>& map,
234  const Key& key, const T default_value) {
235  typedef typename std::map<Key, T>::const_iterator iterator;
236  iterator iter = map.find(key);
237  if (iter == map.end()) return default_value;
238  else return iter->second;
239  } // end of safe_get
240 
241  /**
242  * Transform each key in the map using the key_map
243  * transformation. The resulting map will have the form
244  * output[key_map[i]] = map[i]
245  */
246  template <typename OldKey, typename NewKey, typename T>
247  std::map<NewKey, T>
248  rekey(const std::map<OldKey, T>& map,
249  const std::map<OldKey, NewKey>& key_map) {
250  std::map<NewKey, T> output;
251  typedef std::pair<OldKey, T> pair_type;
252  for(const pair_type& pair: map) {
253  output[safe_get(key_map, pair.first)] = pair.second;
254  }
255  return output;
256  }
257 
258  /**
259  * Transform each key in the map using the key_map
260  * transformation. The resulting map will have the form
261  output[i] = remap[map[i]]
262  */
263  template <typename Key, typename OldT, typename NewT>
264  std::map<Key, NewT>
265  remap(const std::map<Key, OldT>& map,
266  const std::map<OldT, NewT>& val_map) {
267  std::map<Key, NewT> output;
268  typedef std::pair<Key, OldT> pair_type;
269  for(const pair_type& pair: map) {
270  output[pair.first] = safe_get(val_map, pair.second);
271  }
272  return output;
273  }
274 
275  /**
276  * Inplace version of remap
277  */
278  template <typename Key, typename T>
279  void remap(std::map<Key, T>& map,
280  const std::map<T, T>& val_map) {
281  typedef std::pair<Key, T> pair_type;
282  for(pair_type& pair: map) {
283  pair.second = safe_get(val_map, pair.second);
284  }
285  }
286 
287  /**
288  * Computes the union of two maps
289  */
290  template <typename Key, typename T>
291  std::map<Key, T>
292  map_union(const std::map<Key, T>& a,
293  const std::map<Key, T>& b) {
294  // Initialize the output map
295  std::map<Key, T> output;
296  std::set_union(a.begin(), a.end(),
297  b.begin(), b.end(),
298  std::inserter(output, output.begin()),
299  output.value_comp());
300  return output;
301  }
302 
303  /**
304  * Computes the intersection of two maps
305  */
306  template <typename Key, typename T>
307  std::map<Key, T>
308  map_intersect(const std::map<Key, T>& a,
309  const std::map<Key, T>& b) {
310  // Initialize the output map
311  std::map<Key, T> output;
312  // compute the intersection
313  std::set_intersection(a.begin(), a.end(),
314  b.begin(), b.end(),
315  std::inserter(output, output.begin()),
316  output.value_comp());
317  return output;
318  }
319 
320  /**
321  * Returns the entries of a map whose keys show up in the set keys
322  */
323  template <typename Key, typename T>
324  std::map<Key, T>
325  map_intersect(const std::map<Key, T>& m,
326  const std::set<Key>& keys) {
327  std::map<Key, T> output;
328  for(const Key& key: keys) {
329  typename std::map<Key,T>::const_iterator it = m.find(key);
330  if (it != m.end())
331  output[key] = it->second;
332  }
333  return output;
334  }
335 
336  /**
337  * Computes the difference between two maps
338  */
339  template <typename Key, typename T>
340  std::map<Key, T>
341  map_difference(const std::map<Key, T>& a,
342  const std::map<Key, T>& b) {
343  // Initialize the output map
344  std::map<Key, T> output;
345  // compute the intersection
346  std::set_difference(a.begin(), a.end(),
347  b.begin(), b.end(),
348  std::inserter(output, output.begin()),
349  output.value_comp());
350  return output;
351  }
352 
353 
354  /**
355  * Returns the set of keys in a map
356  */
357  template <typename Key, typename T>
358  std::set<Key> keys(const std::map<Key, T>& map) {
359  std::set<Key> output;
360  typedef std::pair<Key, T> pair_type;
361  for(const pair_type& pair: map) {
362  output.insert(pair.first);
363  }
364  return output;
365  }
366 
367  /**
368  * Get the set of keys in a map as a vector
369  */
370  template <typename Key, typename T>
371  std::vector<Key> keys_as_vector(const std::map<Key, T>& map) {
372  std::vector<Key> output(map.size());
373  typedef std::pair<Key, T> pair_type;
374  size_t i = 0;
375  for(const pair_type& pair: map) {
376  output[i++] = pair.first;
377  }
378  return output;
379  }
380 
381 
382  /**
383  * Gets the values from a map
384  */
385  template <typename Key, typename T>
386  std::set<T> values(const std::map<Key, T>& map) {
387  std::set<T> output;
388  typedef std::pair<Key, T> pair_type;
389  for(const pair_type& pair: map) {
390  output.insert(pair.second);
391  }
392  return output;
393  }
394 
395  /**
396  * Gets a subset of values from a map
397  */
398  template <typename Key, typename T>
399  std::vector<T> values(const std::map<Key, T>& m,
400  const std::set<Key>& keys) {
401  std::vector<T> output;
402 
403  for(const Key &i: keys) {
404  output.push_back(safe_get(m, i));
405  }
406  return output;
407  }
408 
409  /**
410  * Gets a subset of values from a map
411  */
412  template <typename Key, typename T>
413  std::vector<T> values(const std::map<Key, T>& m,
414  const std::vector<Key>& keys) {
415  std::vector<T> output;
416  for(const Key &i: keys) {
417  output.push_back(safe_get(m, i));
418  }
419  return output;
420  }
421 
422  /** Creates an identity map (a map from elements to themselves)
423  */
424  template <typename Key>
425  std::map<Key, Key> make_identity_map(const std::set<Key>& keys) {
426  std::map<Key, Key> m;
427  for(const Key& key: keys)
428  m[key] = key;
429  return m;
430  }
431 
432  //! Writes a map to the supplied stream.
433  template <typename Key, typename T>
434  std::ostream& operator<<(std::ostream& out, const std::map<Key, T>& m) {
435  out << "{";
436  for (typename std::map<Key, T>::const_iterator it = m.begin();
437  it != m.end();) {
438  out << it->first << "-->" << it->second;
439  if (++it != m.end()) out << " ";
440  }
441  out << "}";
442  return out;
443  }
444 
445  /** Removes white space (space and tabs) from the beginning and end of str,
446  returning the resultant string
447  */
448  inline std::string trim(const std::string& str) {
449  std::string::size_type pos1 = str.find_first_not_of(" \t");
450  std::string::size_type pos2 = str.find_last_not_of(" \t");
451  return str.substr(pos1 == std::string::npos ? 0 : pos1,
452  pos2 == std::string::npos ? str.size()-1 : pos2-pos1+1);
453  }
454 
455  /**
456  * Convenience function for using std streams to convert anything to a string
457  */
458  template<typename T>
459  std::string tostr(const T& t) {
460  std::stringstream strm;
461  strm << t;
462  return strm.str();
463  }
464 
465  /**
466  * Convenience function for using std streams to convert a string to anything
467  */
468  template<typename T>
469  T fromstr(const std::string& str) {
470  std::stringstream strm(str);
471  T elem;
472  strm >> elem;
473  ASSERT_FALSE(strm.fail());
474  return elem;
475  }
476 
477  /**
478  Returns a string representation of the number,
479  padded to 'npad' characters using the pad_value character
480  */
481  inline std::string pad_number(const size_t number,
482  const size_t npad,
483  const char pad_value = '0') {
484  std::stringstream strm;
485  strm << std::setw((int)npad) << std::setfill(pad_value)
486  << number;
487  return strm.str();
488  }
489 
490 
491  // inline std::string change_suffix(const std::string& fname,
492  // const std::string& new_suffix) {
493  // size_t pos = fname.rfind('.');
494  // assert(pos != std::string::npos);
495  // const std::string new_base(fname.substr(0, pos));
496  // return new_base + new_suffix;
497  // } // end of change_suffix
498 
499 
500  /**
501  Using splitchars as delimiters, splits the string into a vector of strings.
502  if auto_trim is true, trim() is called on all the extracted strings
503  before returning.
504  */
505  inline std::vector<std::string> strsplit(const std::string& str,
506  const std::string& splitchars,
507  const bool auto_trim = false) {
508  std::vector<std::string> tokens;
509  for(size_t beg = 0, end = 0; end != std::string::npos; beg = end+1) {
510  end = str.find_first_of(splitchars, beg);
511  if(auto_trim) {
512  if(end - beg > 0) {
513  std::string tmp = trim(str.substr(beg, end - beg));
514  if(!tmp.empty()) tokens.push_back(tmp);
515  }
516  } else tokens.push_back(str.substr(beg, end - beg));
517  }
518  return tokens;
519  // size_t pos = 0;
520  // while(1) {
521  // size_t nextpos = s.find_first_of(splitchars, pos);
522  // if (nextpos != std::string::npos) {
523  // ret.push_back(s.substr(pos, nextpos - pos));
524  // pos = nextpos + 1;
525  // } else {
526  // ret.push_back(s.substr(pos));
527  // break;
528  // }
529  // }
530  // return ret;
531  }
532 
533  /**
534  * \}
535  */
536 }; // end of namespace turi
537 
538 #endif
#define ASSERT_FALSE(cond)
Definition: assertions.hpp:310
bool is_superset(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:160
std::set< T > set_difference(const std::set< T > &a, const T &b)
Definition: stl_util.hpp:104
std::set< T > set_union(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:57
std::set< Key > keys(const std::map< Key, T > &map)
Definition: stl_util.hpp:358
std::vector< Key > keys_as_vector(const std::map< Key, T > &map)
Definition: stl_util.hpp:371
bool set_equal(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:135
std::map< Key, Key > make_identity_map(const std::set< Key > &keys)
Definition: stl_util.hpp:425
const T & safe_get(const std::map< Key, T > &map, const Key &key)
Definition: stl_util.hpp:219
T fromstr(const std::string &str)
Definition: stl_util.hpp:469
std::map< Key, T > map_difference(const std::map< Key, T > &a, const std::map< Key, T > &b)
Definition: stl_util.hpp:341
std::map< Key, T > map_intersect(const std::map< Key, T > &a, const std::map< Key, T > &b)
Definition: stl_util.hpp:308
std::string trim(const std::string &str)
Definition: stl_util.hpp:448
std::map< Key, T > map_union(const std::map< Key, T > &a, const std::map< Key, T > &b)
Definition: stl_util.hpp:292
#define ASSERT_TRUE(cond)
Definition: assertions.hpp:309
bool includes(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:144
std::map< Key, NewT > remap(const std::map< Key, OldT > &map, const std::map< OldT, NewT > &val_map)
Definition: stl_util.hpp:265
std::set< T > set_intersect(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:79
std::string tostr(const T &t)
Definition: stl_util.hpp:459
std::set< T > values(const std::map< Key, T > &map)
Definition: stl_util.hpp:386
std::pair< std::set< T >, std::set< T > > set_partition(const std::set< T > &s, const std::set< T > &partition)
Definition: stl_util.hpp:116
std::set< T > set_difference(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:91
std::map< NewKey, T > rekey(const std::map< OldKey, T > &map, const std::map< OldKey, NewKey > &key_map)
Definition: stl_util.hpp:248
bool set_disjoint(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:127
std::vector< std::string > strsplit(const std::string &str, const std::string &splitchars, const bool auto_trim=false)
Definition: stl_util.hpp:505
std::string pad_number(const size_t number, const size_t npad, const char pad_value='0')
Definition: stl_util.hpp:481
bool is_subset(const std::set< T > &a, const std::set< T > &b)
Definition: stl_util.hpp:152
std::set< T > set_union(const std::set< T > &a, const T &b)
Definition: stl_util.hpp:69