FreeTensor
Loading...
Searching...
No Matches
container_utils.h
Go to the documentation of this file.
1#ifndef FREE_TENSOR_CONTAINER_UTILS_H
2#define FREE_TENSOR_CONTAINER_UTILS_H
3
4#include <algorithm>
5#include <cctype>
6#include <iostream>
7#include <ranges>
8#include <sstream>
9#include <string>
10#include <tuple>
11#include <unordered_map>
12#include <unordered_set>
13#include <vector>
14
15#include <range/v3/range.hpp>
16#include <range/v3/view.hpp>
17
18namespace freetensor {
19
20namespace views = ranges::views;
21
22template <class T, class V1, class V2, class Hash, class KeyEqual>
23std::unordered_map<T, std::pair<V1, V2>, Hash, KeyEqual>
24intersect(const std::unordered_map<T, V1, Hash, KeyEqual> &lhs,
25 const std::unordered_map<T, V2, Hash, KeyEqual> &rhs) {
26 std::unordered_map<T, std::pair<V1, V2>, Hash, KeyEqual> ret;
27 ret.reserve(std::min(lhs.size(), rhs.size()));
28 for (auto &&[key, v1] : lhs) {
29 if (rhs.count(key)) {
30 ret.emplace(key, std::make_pair(v1, rhs.at(key)));
31 }
32 }
33 return ret;
34}
35
36template <class T, class Hash, class KeyEqual>
37std::unordered_set<T, Hash, KeyEqual>
38intersect(const std::unordered_set<T, Hash, KeyEqual> &lhs,
39 const std::unordered_set<T, Hash, KeyEqual> &rhs) {
40 std::unordered_set<T, Hash, KeyEqual> ret;
41 ret.reserve(std::min(lhs.size(), rhs.size()));
42 for (auto &&key : lhs) {
43 if (rhs.count(key)) {
44 ret.emplace(key);
45 }
46 }
47 return ret;
48}
49
50template <class T, class Hash, class KeyEqual>
51bool hasIntersect(const std::unordered_set<T, Hash, KeyEqual> &lhs,
52 const std::unordered_set<T, Hash, KeyEqual> &rhs) {
53 for (auto &&item : lhs) {
54 if (rhs.count(item)) {
55 return true;
56 }
57 }
58 return false;
59}
60
61template <class T>
62std::vector<T> intersect(const std::vector<T> &lhs, const std::vector<T> &rhs) {
63 std::vector<T> ret;
64 ret.reserve(std::min(lhs.size(), rhs.size()));
65 for (auto &&item : lhs) {
66 if (std::find(rhs.begin(), rhs.end(), item) != rhs.end()) {
67 ret.emplace_back(item);
68 }
69 }
70 return ret;
71}
72
73template <class T, class Hash, class KeyEqual>
74bool isSubSetOf(const std::unordered_set<T, Hash, KeyEqual> &lhs,
75 const std::unordered_set<T, Hash, KeyEqual> &rhs) {
76 for (auto &&item : lhs) {
77 if (!rhs.count(item)) {
78 return false;
79 }
80 }
81 return true;
82}
83
84template <class T>
85std::vector<T> uni(const std::vector<T> &lhs, const std::vector<T> &rhs) {
86 std::vector<T> ret;
87 ret.reserve(std::max(lhs.size(), rhs.size()));
88 ret.insert(ret.end(), lhs.begin(), lhs.end());
89 for (auto &&item : rhs) {
90 if (std::find(lhs.begin(), lhs.end(), item) == lhs.end()) {
91 ret.emplace_back(item);
92 }
93 }
94 return ret;
95}
96template <class T, class Hash, class KeyEqual>
97std::unordered_set<T, Hash, KeyEqual>
98uni(const std::unordered_set<T, Hash, KeyEqual> &lhs,
99 const std::unordered_set<T, Hash, KeyEqual> &rhs) {
100 if (lhs.size() < rhs.size()) {
101 return uni(rhs, lhs);
102 }
103 auto ret = lhs;
104 for (auto &&item : rhs) {
105 ret.insert(item);
106 }
107 return ret;
108}
109
110template <class T, class Hash, class KeyEqual>
111std::unordered_set<T, Hash, KeyEqual>
112diff(const std::unordered_set<T, Hash, KeyEqual> &lhs,
113 const std::unordered_set<T, Hash, KeyEqual> &rhs) {
114 auto ret = lhs;
115 for (auto &&item : rhs) {
116 ret.erase(item);
117 }
118 return ret;
119}
120
121template <class T>
122std::vector<T> cat(const std::vector<T> &lhs, const std::vector<T> &rhs) {
123 std::vector<T> ret;
124 ret.reserve(lhs.size() + rhs.size());
125 ret.insert(ret.end(), lhs.begin(), lhs.end());
126 ret.insert(ret.end(), rhs.begin(), rhs.end());
127 return ret;
128}
129
130template <class T, class U>
131std::vector<T> filter(const std::vector<T> &vec, const U &callback) {
132 std::vector<T> ret;
133 ret.reserve(vec.size());
134 for (auto item : vec) {
135 if (callback(item)) {
136 ret.emplace_back(item);
137 }
138 }
139 return ret;
140}
141
142inline std::string tolower(const std::string &s) {
143 std::string ret;
144 ret.reserve(s.length());
145 for (char c : s) {
146 ret.push_back(std::tolower(c));
147 }
148 return ret;
149}
150
154std::string slice(const std::string &s, int begin, int end);
155inline std::string slice(const std::string &s, int begin) {
156 return slice(s, begin, s.length());
157}
158
159// clang-format off
163template <class T>
164requires std::ranges::range<T> && (!std::convertible_to<T, std::string>)
165std::ostream &operator<<(std::ostream &os, const T &r) {
166 for (auto &&[i, item] : views::enumerate(r)) {
167 os << (i > 0 ? ", " : "") << item;
168 }
169 return os;
170}
171// clang-format on
172
176template <typename... Ts>
177std::ostream &operator<<(std::ostream &os, std::tuple<Ts...> const &tuple) {
178 return std::apply(
179 [&os](Ts const &...t) -> std::ostream & {
180 int i = 0;
181 return ((os << (i++ > 0 ? ", " : "") << t), ...);
182 },
183 tuple);
184}
185
189struct _Join {
190 const std::string &splitter;
191};
192
193template <std::ranges::range Container>
194std::string join(Container &&c, const std::string &splitter) {
195 std::ostringstream oss;
196 bool first = true;
197 for (const auto &s : c) {
198 if (!first)
199 oss << splitter;
200 oss << s;
201 first = false;
202 }
203 return oss.str();
204}
205
206inline auto join(const std::string &splitter) { return _Join{splitter}; }
207
208template <std::ranges::range Container>
209auto operator|(Container &&c, const _Join &joiner) {
210 return join(std::forward<Container>(c), joiner.splitter);
211}
212
213} // namespace freetensor
214
215#endif // FREE_TENSOR_CONTAINER_UTILS_H
Definition: allocator.h:9
auto && lhs
Definition: const_fold.cc:70
std::unordered_set< T, Hash, KeyEqual > diff(const std::unordered_set< T, Hash, KeyEqual > &lhs, const std::unordered_set< T, Hash, KeyEqual > &rhs)
Definition: container_utils.h:112
std::string tolower(const std::string &s)
Definition: container_utils.h:142
std::string slice(const std::string &s, int begin, int end)
Definition: container_utils.cc:6
bool isSubSetOf(const std::unordered_set< T, Hash, KeyEqual > &lhs, const std::unordered_set< T, Hash, KeyEqual > &rhs)
Definition: container_utils.h:74
std::vector< T > filter(const std::vector< T > &vec, const U &callback)
Definition: container_utils.h:131
std::vector< T > uni(const std::vector< T > &lhs, const std::vector< T > &rhs)
Definition: container_utils.h:85
std::string join(Container &&c, const std::string &splitter)
Definition: container_utils.h:194
bool hasIntersect(const std::unordered_set< T, Hash, KeyEqual > &lhs, const std::unordered_set< T, Hash, KeyEqual > &rhs)
Definition: container_utils.h:51
auto auto && rhs
Definition: const_fold.cc:70
std::vector< T > cat(const std::vector< T > &lhs, const std::vector< T > &rhs)
Definition: container_utils.h:122
std::ostream & operator<<(std::ostream &os, const Dependence &dep)
Definition: deps.cc:1404
std::unordered_map< T, std::pair< V1, V2 >, Hash, KeyEqual > intersect(const std::unordered_map< T, V1, Hash, KeyEqual > &lhs, const std::unordered_map< T, V2, Hash, KeyEqual > &rhs)
Definition: container_utils.h:24
auto operator|(Container &&c, const _Join &joiner)
Definition: container_utils.h:209
Definition: container_utils.h:189
const std::string & splitter
Definition: container_utils.h:190