很久沒有上部落格園了,最近一段時間,因為工作的關係時間上比較閒,利用閒暇時間重新翻了一下丟棄很久的C++語言。C++從98、11、14、17目前已經也走到了20版本,發生了很多變化,也引入了很多新的語言特性和庫,讓開發也更加的便、高效。
但用慣了Java後,發現其中Java的容器流式操作特別簡單,封裝的很是優雅。而在C++中,針對容器的操作,與演演算法是完全分隔的,操作起來利用迭代器進行串接,這種方式其實本身實際上覆用效率特別高效,但是對於開發者來說,又顯得有些低效,考慮到這個問題,我自己對C++的容器與演演算法,簡單做了一個封裝。
話不多說,直接上程式碼,讓大家看看效果!
範例程式碼
vector<int> vec = {1, 3, 4, 6, 4, 2, 11, 9};
auto minmax = JavaStyleStream<vector, int>(vec)
.filter([](int i) { return i % 3 == 0; })
.transform([](int i){return i*2.5;})
.sort()
.for_each([](double i) { std::cout << i << " ";})
.minmax();
cout << minmax.first << ":" << minmax.second << endl;
最終結果
7.5 15 22.5 7.5:22.5
看到這裡,是不是覺得容器操作起來要高效很多,不用再面對一成不變的迭代器了。
詳細的Java Style容器流式封裝類,見下面程式碼(未完整封裝C++所有演演算法,工作還在進行中),覺得好用,麻煩點個贊,也歡迎大家提出寶貴意見
//
// Created by AILI on 2022/10/6.
//
#ifndef CPPTEST_JAVASTYLESTREAM_H
#define CPPTEST_JAVASTYLESTREAM_H
#include <algorithm>
#include "function_traits.h"
//template <template<typename, typename> class Cont>
//struct Stream {};
template<template<typename T1, typename T2> class Cont, typename Tp, typename Alloc = std::allocator<Tp>>
class JavaStyleStream {
public:
typedef typename Cont<Tp, Alloc>::value_type value_type;
typedef typename Cont<Tp, Alloc>::pointer pointer;
typedef typename Cont<Tp, Alloc>::const_pointer const_pointer;
typedef typename Cont<Tp, Alloc>::reference reference;
typedef typename Cont<Tp, Alloc>::const_reference const_reference;
typedef typename Cont<Tp, Alloc>::iterator iterator;
typedef typename Cont<Tp, Alloc>::const_iterator const_iterator;
typedef typename Cont<Tp, Alloc>::const_reverse_iterator const_reverse_iterator;
typedef typename Cont<Tp, Alloc>::reverse_iterator reverse_iterator;
typedef typename Cont<Tp, Alloc>::size_type size_type;
typedef typename Cont<Tp, Alloc>::difference_type difference_type;
typedef typename Cont<Tp, Alloc>::allocator_type allocator_type;
//聚合
value_type max() {
return *max_element();
}
template<typename _Compare>
value_type max(_Compare compare) {
return *max_element();
}
iterator max_element() {
return std::max_element(_container.begin(), _container.end());
}
template<typename _Compare>
iterator max_element(_Compare compare) {
return std::max_element(_container.begin(), _container.end(), compare);
}
value_type min() {
return *min_element();
}
template<typename _Compare>
value_type min(_Compare compare) {
return *min_element(compare);
}
iterator min_element() {
return std::min(_container.begin(), _container.end());
}
template<typename _Compare>
iterator min_element(_Compare compare) {
return std::min(_container.begin(), _container.end(), compare);
}
pair<value_type, value_type> minmax() {
pair<const_iterator, const_iterator> r = minmax_element();
return pair<value_type, value_type>(*(r.first), *(r.second));
}
pair<const_iterator, const_iterator> minmax_element() {
return std::minmax_element(_container.begin(), _container.end());
}
template<typename _Compare>
pair<const_iterator, const_iterator> minmax_element(_Compare compare) {
return std::minmax_element(_container.begin(), _container.end(), compare);
}
difference_type count(const value_type& value) {
return std::count(_container.begin(), _container.end(), value);
}
template<typename _Predicate>
difference_type count_if(_Predicate predicate) {
return std::count_if(_container.begin(), _container.end(), predicate);
}
//查詢
template<typename _Predicate>
bool all_of(_Predicate predicate) {
return std::all_of(_container.begin(), _container.end(), predicate);
}
template<typename _Predicate>
bool any_of(_Predicate predicate) {
return std::any_of(_container.begin(), _container.end(), predicate);
}
template<typename _Predicate>
bool none_of(_Predicate predicate) {
return std::none_of(_container.begin(), _container.end(), predicate);
}
iterator adjacent_find() {
return std::adjacent_find(_container.begin(), _container.end());
}
template<typename _BinaryPredicate>
iterator adjacent_find(_BinaryPredicate predicate) {
return std::adjacent_find(_container.begin(), _container.end(), predicate);
}
iterator find(const value_type& value) {
return std::find(_container.begin(), _container.end(), value);
}
template<typename _Predicate>
iterator find_if(_Predicate predicate) {
return std::find_if(_container.begin(), _container.end(), predicate);
}
iterator find_first_of(iterator find_begin, iterator find_end) {
return std::find_first_of(_container.begin(), _container.end(), find_begin, find_end);
}
template<typename _BinaryPredicate>
iterator find_first_of(iterator find_begin, iterator find_end, _BinaryPredicate predicate) {
return std::find_first_of(_container.begin(), _container.end(), find_begin, find_end, predicate);
}
iterator find_end(iterator find_begin, iterator find_end) {
return std::find_end(_container.begin(), _container.end(), find_begin, find_end);
}
template<typename _BinaryPredicate>
iterator find_end(iterator find_begin, iterator find_end, _BinaryPredicate predicate) {
return std::find_end(_container.begin(), _container.end(), find_begin, find_end, predicate);
}
iterator binary_search(const value_type& value) {
return std::binary_search(_container.begin(), _container.end(), value);
}
template<typename _Compare>
iterator binary_search(const value_type& value, _Compare compare) {
return std::binary_search(_container.begin(), _container.end(), value, compare);
}
iterator search(const value_type& value) {
return std::search(_container.begin(), _container.end(), value);
}
template<typename _BinaryPredicate>
iterator search(iterator find_begin, iterator find_end, _BinaryPredicate predicate) {
return std::search(_container.begin(), _container.end(), find_begin, find_end, predicate);
}
iterator search_n(size_type n, const value_type& value) {
return std::search_n(_container.begin(), _container.end(), n, value);
}
template<typename _BinaryPredicate>
iterator search_n(size_type n, const value_type& value, _BinaryPredicate predicate) {
return std::search_n(_container.begin(), _container.end(), n, value, predicate);
}
iterator lower_bound(const value_type& value) {
return std::lower_bound(_container.begin(), _container.end(), value);
}
template<typename _Compare>
iterator lower_bound(const value_type& value, _Compare compare) {
return std::lower_bound(_container.begin(), _container.end(), value, compare);
}
iterator upper_bound(const value_type& value) {
return std::upper_bound(_container.begin(), _container.end(), value);
}
template<typename _Compare>
iterator upper_bound(const value_type& value, _Compare compare) {
return std::upper_bound(_container.begin(), _container.end(), value, compare);
}
//排序
bool is_sorted() {
return std::is_sorted(_container.begin(), _container.end());
}
template<typename _Compare>
bool is_sorted(_Compare compare) {
return std::is_sorted(_container.begin(), _container.end(), compare);
}
bool is_sorted_until() {
return std::is_sorted_until(_container.begin(), _container.end());
}
template<typename _Compare>
bool is_sorted_until(_Compare compare) {
return std::is_sorted_until(_container.begin(), _container.end(), compare);
}
JavaStyleStream& sort() {
std::sort(_container.begin(), _container.end());
return *this;
}
template<typename _Compare>
JavaStyleStream& sort(_Compare compare) {
std::sort(_container.begin(), _container.end(), compare);
return *this;
}
template<typename _Integer>
JavaStyleStream& partial_sort(_Integer integer) {
std::partial_sort(_container.begin(), _container.begin() + integer, _container.end());
return *this;
}
template<typename _Integer, typename _Compare>
JavaStyleStream& partial_sort(_Integer integer, _Compare compare) {
std::partial_sort(_container.begin(), _container.begin() + integer, _container.end(), compare);
return *this;
}
JavaStyleStream& stable_sort() {
std::stable_sort(_container.begin(), _container.end());
return *this;
}
template<typename _Compare>
JavaStyleStream& stable_sort(_Compare compare) {
std::stable_sort(_container.begin(), _container.end(), compare);
return *this;
}
template<typename _Integer>
JavaStyleStream& nth_element(_Integer integer) {
std::nth_element(_container.begin(), _container.begin() + integer, _container.end());
return *this;
}
template<typename _Integer, typename _Compare>
JavaStyleStream& nth_element(_Integer integer, _Compare compare) {
std::nth_element(_container.begin(), _container.begin() + integer, _container.end(), compare);
return *this;
}
JavaStyleStream& shuffle() {
std::shuffle(_container.begin(), _container.end());
return *this;
}
template<typename _Generator>
JavaStyleStream& shuffle(_Generator generator) {
std::shuffle(_container.begin(), _container.end(), generator);
return *this;
}
JavaStyleStream& random_shuffle() {
std::random_shuffle(_container.begin(), _container.end());
return *this;
}
template<typename _Generator>
JavaStyleStream& random_shuffle(_Generator generator) {
std::random_shuffle(_container.begin(), _container.end(), generator);
return *this;
}
//刪除&替換
JavaStyleStream& remove_erase(const value_type& value) {
_container.erase(std::remove(_container.begin(), _container.end(), value), _container.end());
return *this;
}
template<typename _Predicate>
JavaStyleStream& remove_erase(_Predicate predicate) {
_container.erase(std::remove_if(_container.begin(), _container.end(), predicate), _container.end());
return *this;
}
JavaStyleStream& repalce(const value_type& old_value, const value_type& new_value) {
std::replace(_container.begin(), _container.end(), old_value, new_value);
return *this;
}
template<typename _Predicate>
JavaStyleStream& replace_if(_Predicate predicate, const value_type& new_value) {
std::remove_if(_container.begin(), _container.end(), predicate, new_value);
return *this;
}
//反轉&旋轉
JavaStyleStream& reverse() {
std::reverse(_container.begin(), _container.end());
return *this;
}
template<typename _Integer>
JavaStyleStream& reverse(_Integer integer) {
std::rotate(_container.begin(), _container.begin() + integer, _container.end());
return *this;
}
//歸一化
JavaStyleStream& unique() {
std::unique(_container.begin(), _container.end());
return *this;
}
template<typename _BinaryPredicate>
JavaStyleStream& unique(_BinaryPredicate predicate) {
std::unique(_container.begin(), _container.end(), predicate);
return *this;
}
//分組(是否需要返回分組迭代器?)
template<typename _Predicate>
JavaStyleStream& partition(_Predicate predicate) {
std::partition(_container.begin(), _container.end(), predicate);
return *this;
}
template<typename _Predicate>
JavaStyleStream& stable_partition(_Predicate predicate) {
std::stable_partition(_container.begin(), _container.end(), predicate);
return *this;
}
//C++11提供
template<typename _Predicate>
JavaStyleStream& partition_point(_Predicate predicate) {
std::partition_point(_container.begin(), _container.end(), predicate);
return *this;
}
//過濾&複製&合併&轉換
template<typename _Predicate>
JavaStyleStream filter(_Predicate predicate) {
Cont<Tp, Alloc> newCont;
for(iterator iter = _container.begin(); iter != _container.end(); ++iter) {
if (predicate(*iter)) {
newCont.push_back(*iter);
}
}
JavaStyleStream<Cont, Tp> newSteram(newCont);
return std::move(newSteram);
}
template<typename _UnaryFunction>
JavaStyleStream<Cont, typename function_traits<_UnaryFunction>::return_type> transform(_UnaryFunction function) {
Cont<typename function_traits<_UnaryFunction>::return_type, std::allocator<typename function_traits<_UnaryFunction>::return_type>> newCont;
std::transform(_container.begin(), _container.end(), std::back_inserter(newCont), function);
JavaStyleStream<Cont, typename function_traits<_UnaryFunction>::return_type, std::allocator<typename function_traits<_UnaryFunction>::return_type>> newStream(newCont);
return std::move(newStream);
}
//複製
JavaStyleStream copy() {
Cont<Tp, Alloc> newCont;
std::copy(_container.begin(), _container.end(), std::back_inserter(newCont));
JavaStyleStream<Cont, Tp> newStream(newCont);
return newStream;
}
template<typename _Predicate>
JavaStyleStream copy_if(_Predicate predicate) {
Cont<Tp, Alloc> newCont;
std::copy_if(_container.begin(), _container.end(), std::back_inserter(newCont), predicate);
JavaStyleStream<Cont, Tp> newStream(newCont);
return newStream;
}
template<typename _Integer>
JavaStyleStream copy_n(_Integer integer) {
Cont<Tp, Alloc> newCont;
std::copy_n(_container.begin(), integer, std::back_inserter(newCont));
JavaStyleStream<Cont, Tp> newStream(newCont);
return newStream;
}
JavaStyleStream copy_backward() {
Cont<Tp, Alloc> newCont;
std::copy_backward(_container.begin(), _container.end(), std::back_inserter(newCont));
JavaStyleStream<Cont, Tp> newStream(newCont);
return newStream;
}
//遍歷
template<typename _Function>
JavaStyleStream& for_each(_Function function) {
std::for_each(_container.begin(), _container.end(), function);
return *this;
}
//reduce
//集合
public:
JavaStyleStream(Cont<Tp, Alloc>& container)
: _container(container)
{};
JavaStyleStream(JavaStyleStream& stream)
: _container(stream._container)
{};
JavaStyleStream(JavaStyleStream&& stream)
: _container(stream._container)
{};
private:
Cont<Tp, Alloc> _container;
};
#endif //CPPTEST_JAVASTYLESTREAM_H