C++11提供了多种迭代容器的方法。例如:
基于范围的循环
for(auto c : container) fun(c)
std::for_each
for_each(container.begin(),container.end(),fun)
然而,迭代两个(或更多)大小相同的容器以完成类似以下操作的推荐方法是什么:
for(unsigned i = 0; i < containerA.size(); ++i) {
containerA[i] = containerB[i];
}
C++11提供了多种迭代容器的方法。例如:
for(auto c : container) fun(c)
for_each(container.begin(),container.end(),fun)
然而,迭代两个(或更多)大小相同的容器以完成类似以下操作的推荐方法是什么:
for(unsigned i = 0; i < containerA.size(); ++i) {
containerA[i] = containerB[i];
}
这个变体将不同的序列压缩成一个可以在结构化绑定中使用的元组向量。
您可以使用任意数量的序列。
非常简单和高效。
#include <iostream>
#include <utility>
#include <algorithm>
#include <cstddef>
#include <tuple>
#include <vector>
#include <string>
#include <array>
#include <map>
template<typename... Container>
auto zip(Container&... containers) noexcept {
using tuple_type = std::tuple<std::decay_t<decltype(*std::begin(containers))>&...>;
std::size_t container_size = std::min({ std::size(containers)... });
std::vector<tuple_type> result;
result.reserve(container_size);
auto iterators = std::make_tuple(std::begin(containers)...);
for (std::size_t i = 0; i < container_size; ++i) {
std::apply([&result](auto&... it) {
result.emplace_back(*it++...);
}, iterators);
}
return result;
}
int main() {
std::vector v1 = { 1.1, 1.2, 1.3 };
std::array v2 = { 1, 2, 3 };
std::map<std::string, int> v3;
v3["key1"] = 1;
v3["key2"] = 2;
v3["key3"] = 3;
int arr[] = { 3, 2, 1 };
for (const auto& [val1, val2, val3, val4] : zip(v1, v2, v3, arr)) {
std::cout << "vector -> " << val1;
std::cout << "\narray -> " << val2;
std::cout << "\nmap -> " << val3.first << '|' << val3.second;
std::cout << "\nC-array -> " << val4;
std::cout << "\n\n";
}
std::cout.flush();
return 0;
}
如果你想要更高效的方法,你也可以尝试这种constexpr
的方法:
(请注意,结构化绑定必须始终为auto
)
#include <iostream>
#include <utility>
#include <algorithm>
#include <iterator>
#include <cstddef>
#include <tuple>
#include <vector>
#include <string>
#include <array>
#include <map>
template<typename... Container>
class zippable {
public:
using tuple_type_t = std::tuple<std::decay_t<decltype(*std::begin(std::declval<Container&>()))>&...>;
using iterator_tuple_t = std::tuple<decltype(std::begin(std::declval<Container&>()))...>;
constexpr zippable(Container&... containers) noexcept :
iterators_begin(std::make_tuple(std::begin(containers)...)),
iterators_end(std::make_tuple(std::end(containers)...)) {}
class iterator {
public:
constexpr iterator(const iterator_tuple_t& it) noexcept : iterators(it) {}
constexpr iterator(iterator_tuple_t&& it) noexcept : iterators(std::move(it)) {}
constexpr iterator& operator++() {
std::apply([](auto&... it) {
((it++), ...);
}, iterators);
return *this;
}
constexpr tuple_type_t operator*() {
return std::apply([](auto&... it) -> tuple_type_t {
return std::forward_as_tuple(*it...);
}, iterators);
}
constexpr bool operator==(const iterator& other) const {
return iterators == other.iterators;
}
constexpr bool operator!=(const iterator& other) const {
return iterators != other.iterators;
}
private:
iterator_tuple_t iterators;
};
constexpr iterator begin() noexcept {
return iterator(iterators_begin);
}
constexpr iterator end() noexcept {
return iterator(iterators_end);
}
private:
iterator_tuple_t iterators_begin;
iterator_tuple_t iterators_end;
};
int main() {
std::vector v1 = { 1.1, 1.2, 1.3 };
std::array v2 = { 1, 2, 3 };
std::map<std::string, int> v3;
v3["key1"] = 1;
v3["key2"] = 2;
v3["key3"] = 3;
int arr[] = { 3, 2, 1 };
for (auto [val1, val2, val3, val4] : zippable(v1, v2, v3, arr)) {
std::cout << "vector -> " << val1;
std::cout << "\narray -> " << val2;
std::cout << "\nmap -> " << val3.first << '|' << val3.second;
std::cout << "\nC-array -> " << val4;
std::cout << "\n\n";
}
std::cout.flush();
return 0;
}
这是一个变体
template<class ... Iterator>
void increment_dummy(Iterator ... i)
{}
template<class Function,class ... Iterator>
void for_each_combined(size_t N,Function&& fun,Iterator... iter)
{
while(N!=0)
{
fun(*iter...);
increment_dummy(++iter...);
--N;
}
}
使用示例
void arrays_mix(size_t N,const float* x,const float* y,float* z)
{
for_each_combined(N,[](float x,float y,float& z){z=x+y;},x,y,z);
}
#include <algorithm>
中的transform
怎么样? - Ankit AcharyacontainerA = containerB;
代替循环。 - emlai