int sum = 0; for (std::vector<int>::iterator it = candles.begin(); it != candles.end(); it++) sum += it->ClosePrice;
int sum = 0; Iterator it = al.iterator(); while (it.hasNext()) { it = it.next(); sum += it.ClosePrice; }
.begin()
and .end()
- these are two parts of the same entity. If these two parts were taken and combined into one entity ... It is said - done (the idea was borrowed from Alexandrescu from the “Iterators Must Go” presentation): template<typename TIter> class IterRange { public: typedef typename std::iterator_traits<TIter>::value_type value_type; IterRange(TIter b, TIter e) : b(b), e(e) { } bool empty() { return (b == e); } value_type popFront() { assert(!empty()); return *(b++); } value_type popBack() { assert(!empty()); return *(--e); } value_type front() { assert(!empty()); return *b; } value_type back() { assert(!empty()); TIter tmp = e; return *(--tmp); } private: TIter b; TIter e; };
back()
and popBack()
methods also do not interfere. template<typename R, typename F> class WhereRange { public: typedef typename R::value_type value_type; WhereRange(R r, F f) : r(r), f(f) , frontReady(false) , backReady(false) { } bool empty() { if (!frontReady) seekFront(); return r.empty(); } value_type popFront() { if (!frontReady) seekFront(); auto tmp = *this; r.popFront(); frontReady = false; return tmp.front(); } value_type popBack() { // } value_type front() { if (!frontReady) seekFront(); return r.front(); } value_type back() { // } private: void seekFront() { while(!r.empty() && !f(r.front())) r.popFront(); frontReady = true; } void seekBack() { // } private: R r; F f; bool frontReady; bool backReady; };
int max = arr.Where(...).OrderBy(...).Select(...).Max();
template<template<typename> class TLinq, typename R> class WhereRange_mixin { public: template<typename F> TLinq<WhereRange<R,F> > where(F f) const { return boolinq::where(((TLinq<R>*)this)->r,f); } };
template<typename R> class Linq : public SkipRange_mixin<Linq,R> , public TakeRange_mixin<Linq,R> , public WhereRange_mixin<Linq,R> , public SelectRange_mixin<Linq,R> , public ReverseRange_mixin<Linq,R> , public OrderByRange_mixin<Linq,R> // ... ... { public: typedef typename R::value_type value_type; Linq(const R & r) : r(r) { } bool empty() { return r.empty(); } value_type popFront() { return r.popFront(); } value_type popBack() { return r.popBack(); } value_type front() { return r.front(); } value_type back() { return r.back(); } public: R r; };
template<typename R> class ReverseRange { public: typedef typename R::value_type value_type; ReverseRange(R r) : r(r) { } bool empty() { return r.empty(); } value_type popFront() { return r.popBack(); } value_type popBack() { return r.popFront(); } value_type front() { return r.back(); } value_type back() { return r.front(); } template<typename R2> friend R2 reverse(ReverseRange<R2> r); // smart needed private: R r; };
template<typename R> ReverseRange<R> reverse(R r) { return r; } // Unwrap for double-reverse case template<typename R> R reverse(ReverseRange<R> r) { return rr; // smart }
template<template<typename> class TLinq, typename R> class ReverseRange_mixin { public: TLinq<ReverseRange<R> > reverse() const { return boolinq::reverse(((TLinq<R>*)this)->r); } }; // Unwrap for double-reverse case template<template<typename> class TLinq, typename T> class ReverseRange_mixin<TLinq,ReverseRange<T> > { public: TLinq<T> reverse() const { return boolinq::reverse(((TLinq<ReverseRange<T> >*)this)->r); } };
Linq<ReverseRange<XxxRange<...>>>
and expands it to Linq<XxxRange<...>>
. Brain broke while got compiled code. boolinq::from<CustomLinq>(arr)
boolinq::from(arr)
using namespace boolinq; int sum = sum(select(where(from(arr), [](...){...}), [](...){...}));
srand(0xDEADBEEF); std::vector<int> vec(100000000, 0); for (unsigned i = 0; i < vec.size(); i++) vec[i] = rand();
// double sum = 0; int count = 0; for (unsigned i = 0; i < vec.size(); i++) { if (vec[i] % 2 == 1) { sum += vec[i]; count++; } } double avgValue = sum / count; // avgValue double disperSum = 0; for (unsigned i = 0; i < vec.size(); i++) if (vec[i] % 2 == 1) disperSum += (vec[i] - avgValue)*(vec[i] - avgValue); double disper = disperSum / count;
// double avgValue = from(vec).where( [](int a){return a%2 == 1;}) .cast<double>() .avg(); // avgValue double disper = from(vec).where( [](int a){return a%2 == 1;}) .select([=](int a){return (a-avgValue)*(a-avgValue);}) .cast<double>() .avg();
C ++ Code | 1207 ms |
C ++ code with iterators | 1224 ms |
Boolinq code | 1564 ms |
.begin()
and .end()
methods to the Linq class for backward compatibility with STL.Source: https://habr.com/ru/post/142657/
All Articles