fork download
  1. #pragma once
  2.  
  3. #include <algorithm>
  4. #include <array>
  5. #include <functional>
  6. #include <vector>
  7.  
  8. #include <boost/phoenix/core.hpp>
  9. #include <boost/phoenix/operator.hpp>
  10.  
  11. using boost::phoenix::arg_names::arg1;
  12. using boost::phoenix::arg_names::arg2;
  13.  
  14. // Voodoo magic to get the friend function to work
  15. // Thanks Cheers and hth. - Alf
  16. template<class Enumerable>
  17. class Container;
  18.  
  19. template<class Enumerable>
  20. Container<Enumerable> From(Enumerable& source);
  21. // End of Voodoo magic
  22.  
  23. template<typename Enumerable>
  24. class Container
  25. {
  26. public:
  27. friend Container From<Enumerable>(Enumerable& source);
  28.  
  29. template<typename T>
  30. operator T()
  31. {
  32. T t;
  33. std::copy(items_.begin(), items_.end(), std::back_inserter(t));
  34.  
  35. return t;
  36. }
  37.  
  38. template<class Predicate>
  39. Container Where(Predicate p)
  40. {
  41. Container filteredContainer;
  42. std::copy_if(items_.begin(), items_.end(), std::back_inserter(filteredContainer.items_), p);
  43.  
  44. return filteredContainer;
  45. }
  46.  
  47.  
  48. Container Take(size_t n)
  49. {
  50. // Add assert on n
  51. Container subContainer;
  52. std::copy(items_.begin(), items_.begin() + n-1, std::back_inserter(subContainer.items_));
  53.  
  54. return subContainer;
  55. }
  56.  
  57.  
  58. template<class Predicate>
  59. Container TakeWhile(Predicate p)
  60. {
  61. Container subContainer;
  62. auto it = items_.begin();
  63. auto end = items_.end();
  64.  
  65. // Increment it only and use range copy instead of multiple push_back
  66. while(p(*it) && it != end)
  67. {
  68. subContainer.items_.push_back(*it);
  69. it++;
  70. }
  71.  
  72. return subContainer;
  73. }
  74.  
  75.  
  76. Container Skip(size_t n)
  77. {
  78. // Add assert on n
  79. Container subContainer;
  80. std::copy(items_.begin() + n-1, items_.end(), std::back_inserter(subContainer.items_));
  81.  
  82. return subContainer;
  83. }
  84.  
  85.  
  86. template<class Predicate>
  87. Container SkipWhile(Predicate p)
  88. {
  89. Container subContainer;
  90. auto it = items_.begin();
  91. auto end = items_.end();
  92.  
  93. while(p(*it) && it != end)
  94. {
  95. it++;
  96. }
  97.  
  98. std::copy(it, end, std::back_inserter(subContainer);
  99.  
  100. return subContainer;
  101. }
  102.  
  103.  
  104. size_t Count()
  105. {
  106. return items_.size();
  107. }
  108.  
  109.  
  110. template<class Predicate>
  111. size_t Count(Predicate p)
  112. {
  113. return std::count_if(items_.begin(), items_.end(), p);
  114. }
  115.  
  116.  
  117. template<class Function>
  118. void ForEach(Function f)
  119. {
  120. std::for_each(items_.begin(), items_.end(), f);
  121. }
  122.  
  123.  
  124. typename Enumerable::value_type Sum()
  125. {
  126. auto it = items_.begin();
  127. auto end = items_.end();
  128.  
  129. Enumerable::value_type sum = *(it++);
  130. while(it != end)
  131. {
  132. sum += *it;
  133. it++;
  134. }
  135.  
  136. return sum;
  137. }
  138.  
  139.  
  140. typename Enumerable::value_type Min()
  141. {
  142. auto it = items_.begin();
  143. auto end = items_.end();
  144.  
  145. Enumerable::value_type min = *(it++);
  146. while(it != end)
  147. {
  148. if((*it) < min)
  149. {
  150. min = *it;
  151. }
  152. it++;
  153. }
  154.  
  155. return min;
  156. }
  157.  
  158.  
  159. typename Enumerable::value_type Max()
  160. {
  161. auto it = items_.begin();
  162. auto end = items_.end();
  163.  
  164. Enumerable::value_type max = *(it++);
  165. while(it != end)
  166. {
  167. if((*it) > max)
  168. {
  169. max = *it;
  170. }
  171. it++;
  172. }
  173.  
  174. return max;
  175. }
  176.  
  177.  
  178. typename Enumerable::value_type Average()
  179. {
  180. return Sum()/Count();
  181. }
  182.  
  183. template<class Function>
  184. typename Enumerable::value_type Aggregate(Function f)
  185. {
  186. auto it = items_.begin();
  187. auto end = items_.end();
  188.  
  189. Enumerable::value_type aggregate = *(it++);
  190. while(it != end)
  191. {
  192. aggregate = f(aggregate, *(it++));
  193. }
  194.  
  195. return aggregate;
  196. }
  197.  
  198. typename Enumerable::value_type ElementAt(unsigned int index)
  199. {
  200. // Use boost::optional?
  201. return items_[index];
  202. }
  203.  
  204. private:
  205. Container(): items_() {}
  206.  
  207.  
  208. Container(Enumerable& source): items_()
  209. {
  210. std::copy(std::begin(source), std::end(source), std::back_inserter(items_));
  211. }
  212.  
  213.  
  214. std::vector<typename Enumerable::value_type> items_;
  215. };
  216.  
  217.  
  218. template<typename Enumerable>
  219. Container<Enumerable> From(Enumerable& source)
  220. {
  221. return Container<Enumerable>(source);
  222. }
  223.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty