Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为向量的向量提供平坦迭代器的优雅方式_C++_C++11_Vector_C++14 - Fatal编程技术网

C++ 为向量的向量提供平坦迭代器的优雅方式

C++ 为向量的向量提供平坦迭代器的优雅方式,c++,c++11,vector,c++14,C++,C++11,Vector,C++14,我有一个适配器,其目标是为pair值pair提供正向迭代器。然而,在我的内部表示中,我将数据存储为向量 因此,在迭代过程中,我需要将它展平,并将每一个字符串,也就是像“今天大量滴油”这样的短句,转换为FeatureVector 在原始版本中,我有如下内容: { {"Oil drops massively","OPEC surge oil produciton","Brent price goes up" -> "OIL_LABEL"}, {"France consume more

我有一个适配器,其目标是为pair值
pair
提供正向迭代器。然而,在我的内部表示中,我将数据存储为
向量

因此,在迭代过程中,我需要将它展平,并将每一个
字符串
,也就是像“今天大量滴油”这样的短句,转换为
FeatureVector

在原始版本中,我有如下内容:

{
  {"Oil drops massively","OPEC surge oil produciton","Brent price goes up" -> "OIL_LABEL"}, 
  {"France consume more vine", "vine production in Italy drops" -> "VINE_LABEL"}
}
我需要将其转换为:

{
  vectorize("Oil drops massively") -> "OIL_LABEL", 
  vectorize("OPEC surge oil produciton") -> "OIL_LABEL", ... , 
  vectorize("vine production in Italy drops") -> "VINE_LABEL"
}
vectorize()
->它是从句子到稀疏向量的转换,就像这样
“纽约证券交易所的油滴”->{0,1,0..0,1,0..0,1}

最简单的方法是创建新的向量,用所有数据初始化它,然后使用它的迭代器,但这是一个非常耗费资源的操作,所以理想情况下,我希望这种转换在每次迭代中完成。这种转换最优雅的方式是什么

这是用于存储文本语料库的数据结构的简化版本。之后需要在分类器初始化中使用迭代器,这需要两个迭代器:
开始
结束
,这在逻辑上与
向量
中的迭代器相同一个简单的范围类型:

template<class It>
struct range_t {
  It b{},e{};
  It begin() const {return b;}
  It end() const {return e;}
  bool empty() const {return begin()==end();}
  friend bool operator==(range_t lhs, range_t rhs){
    if (lhs.empty() && rhs.empty()) return true;
    return lhs.begin() == rhs.begin() && lhs.end() == rhs.end();
  }
  friend bool operator!=(range_t lhs, range_t rhs){
    return !(lhs==rhs);
  }
  range_t without_front( std::size_t N = 1 ) const {
    return { std::next(begin(), N), end() };
  }
  range_t without_back( std::size_t N = 1 ) const {
    return { begin(), std::prev(end(),N) };
  }
  decltype(auto) front() const {
    return *begin();
  }
  decltype(auto) back() const {
    return *std::prev(end());
  }
};
template<class It>
range_t<It> range( It b, It e ) {
  return {b,e};
}
模板
结构范围{
它是b{},e{};
它的begin()常量{return b;}
It end()常量{return e;}
bool empty()常量{return begin()==end();}
friend bool运算符==(范围左,范围右){
if(lhs.empty()&&rhs.empty())返回true;
返回lhs.begin()==rhs.begin()&&lhs.end()==rhs.end();
}
friend bool运算符!=(范围左,范围右){
返回!(lhs==rhs);
}
不带前端的范围(标准::大小N=1)常数{
返回{std::next(begin(),N),end()};
}
没有返回的范围(标准::大小N=1)常数{
返回{begin(),std::prev(end(),N)};
}
decltype(自动)前端()常量{
返回*begin();
}
decltype(auto)back()常量{
return*std::prev(end());
}
};
模板
范围\u t范围(It b、It e){
返回{b,e};
}
下面是一个不兼容的伪迭代器,它执行两个rane的叉积:

template<class ItA, class ItB>
struct cross_iterator_t {
  range_t<ItA> cur_a;
  range_t<ItB> orig_b;
  range_t<ItB> cur_b;

  cross_iterator_t( range_t<ItA> a, range_t<ItB> b ):
    cur_a(a), orig_b(b), cur_b(b)
  {}

  bool empty() const { return cur_a.empty() || cur_b.empty(); }

  void operator++(){
    cur_b = cur_b.without_front();
    if (cur_b.empty()) {
      cur_a = cur_a.without_front();
      if (cur_a.empty()) return;
      cur_b = orig_b;
    }
  }
  auto operator*()const {
    return std::make_pair( cur_a.front(), cur_b.front() );
  }
  friend bool operator==( cross_iterator_t lhs, cross_iterator_t rhs ) {
    if (lhs.empty() && rhs.empty()) return true;

    auto mytie=[](auto&& self){
      return std::tie(self.cur_a, self.cur_b);
    };
    return mytie(lhs)==mytie(rhs);
  }
  friend bool operator!=( cross_iterator_t lhs, cross_iterator_t rhs ) {
    return !(lhs==rhs);
  }
};
template<class Lhs, class Rhs>
auto cross_iterator( range_t<Lhs> a, range_t<Rhs> b )
-> cross_iterator_t<Lhs, Rhs>
{
  return {a,b};
}
模板
结构交叉迭代器{
量程电流;
原始范围;
量程电流;
交叉迭代器(范围a,范围b):
电流a(a)、电流b(b)、电流b(b)
{}
bool empty()常量{return cur_a.empty()| | cur_b.empty()|}
void运算符++(){
cur_b=不带_front()的cur_b;
if(cur_b.empty()){
cur_a=cur_a.不带_front();
if(cur_a.empty())返回;
cur_b=orig_b;
}
}
自动运算符*()常量{
return std::make_pair(cur_a.front(),cur_b.front());
}
friend bool运算符==(交叉迭代器lhs,交叉迭代器rhs){
if(lhs.empty()&&rhs.empty())返回true;
自动mytie=[](自动和自){
返回标准::tie(self.cur\u a、self.cur\u b);
};
返回mytie(lhs)=mytie(rhs);
}
friend bool运算符!=(交叉迭代器lhs,交叉迭代器rhs){
返回!(lhs==rhs);
}
};
模板
自动交叉迭代器(范围a,范围b)
->交叉迭代器
{
返回{a,b};
}
从这里,您可以获取
std::vector,B
并执行以下操作:

template<class A, class B>
auto cross_one_element( A& range_a, B& b_element ) {
  auto a = range( std::begin(range_a), std::end(range_a) );
  auto b = range( &b_element, (&b_element) +1 );
  auto s = cross_iterator(a, b);
  decltype(s) f{};
  return cross_iterator(s, f);
}
模板
自动交叉元素(A和范围元素A、B和B元素){
自动a=范围(标准::开始(范围a),标准::结束(范围a));
自动b=范围(&b_元素,(&b_元素)+1);
自动s=交叉迭代器(a,b);
decltype(s)f{};
返回交叉迭代器(s,f);
}
这就解决了你的一个问题。需要修复以上内容以支持真正的输入迭代器特性,而不仅仅是上述与(:)一起工作的伪迭代器

然后,您必须编写代码,将向量X转换为函数f的f(X)范围

然后,您必须编写一系列的代码,并将其展平到一个范围内

这些步骤中的每一步都不比上面的难

有些库可以为您执行此操作。boost有一些,Rangesv3有一些,还有一堆其他范围操纵库

Boost甚至允许您通过指定在
*
和下一步以及
=
上执行的操作来编写迭代器。当一个子向量为空时,要想知道该怎么办仍然很棘手,所以在这种情况下使用更通用的算法可能是明智的


上面的代码没有经过测试,是C++14。C++11版本只是更加冗长。

您到底需要如何迭代<只针对(:)一次循环一次?您需要将
向量中的每个
字符串
转换为
特征向量
,或者您需要将
向量
转换为
特征向量
?什么是
特征向量
?你需要把什么变成什么?不,那没用。“我需要一个开始和结束迭代器”并没有确切地告诉我如何使用这些迭代器。它们需要是随机访问迭代器吗?前向迭代器?输入迭代器?请告诉我您需要的最弱迭代器。您需要的越多,解决方案就越困难,成本也就越高。第二个问题:boost可以接受吗?您可能不太精确。例如,“将
字符串
转换为
特征向量
”是。。。(1) 从单个
字符串
构造
特征向量
,或(2)从
向量
构造
特征向量
,或(3)其他。