-
Notifications
You must be signed in to change notification settings - Fork 1
/
Map.h
126 lines (114 loc) · 4.2 KB
/
Map.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#ifndef SFL_MAP_H
#define SFL_MAP_H
#include <map>
#include <utility>
#include "Prelude.h"
/**
* These function operate on maps, typically std::map or std::unordered_map
*/
namespace sfl
{
/**
* Return all keys of the map. keys will be in ascending order if M is an std::map
*/
template<typename M,typename A = typename M::key_type,typename B = typename M::mapped_type>
std::vector<A> keys(const M &m)
{
return map(&fst<A,B>, m);
}
namespace Map
{
/*
* O(1) A map with a single element
*/
template<typename K,typename V>
std::map<K,V> singleton(const K &k, const V &v)
{
std::map<K,V> ret;
ret.insert(std::make_pair(k,v));
return ret;
}
/*
* O(n*log n). Build a map from a list of key/value pairs. If the list contains more than one value for the range
* same key, the last value for the key is retained.
*/
template<typename R,typename M = typename std::map<typename R::value_type::first_type,typename R::value_type::second_type>>
M fromRange(const R &r)
{
return M(r.begin(),r.end());
}
/*
* O(n) in case of std::map. Convert to a list of key/value pairs.
*/
template<typename M,typename A = typename M::key_type,typename B = typename M::mapped_type,typename R = typename std::vector<std::pair<A,B>>>
R toVector(const M &m)
{
return R(m.begin(),m.end());
}
/*
* Because of c++ limitations, this is just a synonym for fromRange. Semantically,
* an already ordered list should be passed here.
*/
template<typename R,typename M = typename std::map<typename R::value_type::first_type,typename R::value_type::second_type>>
M fromAscRange(const R &r)
{
return fromRange(r);
}
/*
* Build a map from a list of key/value pairs with a combining function.
*/
template<typename R,typename F,typename A = typename R::value_type::first_type,typename B = typename R::value_type::second_type,typename M = typename std::map<A,B>>
M fromRangeWith(F &&f, const R &r)
{
M ret;
for (auto &p : r) {
auto itAndSuccess = ret.insert(std::make_pair(p.first,p.second));
if (!itAndSuccess.second) {
B &value = itAndSuccess.first->second;
value = f(value, p.second);
}
}
return std::move(ret);
}
/*
* Group pairs based on firsts, and build a map where the keys are the first, and the values are vectors of seconds
* For example: [(1,"aa"),(1,"cc"),(2,"aa"),(3,"ff"),(3,"gg"),(1,"bb")] becomes a map of
* [(1,["bb","cc","aa"]),(2,["aa"]),(3,["gg","ff"])]
*/
template<typename R,typename A = typename R::value_type::first_type,typename B = typename R::value_type::second_type,typename M = typename std::map<A,typename std::vector<B>>>
M sortAndGroup(const R &r)
{
return fromRangeWith(plus<std::vector<B>>, map([](const std::pair<A,B> &p){
return std::make_pair(p.first,std::vector<B>{{p.second}});
},r));
}
/*
* O(n*m). The expression (union t1 t2) takes the left-biased union of t1 and t2. It prefers t1
* when duplicate keys are encountered, i.e.
*/
template<typename M>
M mapUnion(const M &lhs,const M &rhs)
{
auto ret = lhs;
for (const auto &p : rhs) {
ret.insert(p);
}
return ret;
}
/*
* The union of a range of maps
*/
template<typename R,typename M = typename R::value_type>
M unionsR(const R &r)
{
return foldlR(mapUnion<M>, M(),r);
}
template<typename M,typename A = typename M::key_type,typename B = typename M::mapped_type>
B findWithDefault(const B &def, const A &key, const M &m)
{
auto it = m.find(key);
return it == m.end() ? def : it->second;
}
}
}
#endif