【问题标题】:C++ best way to split vector into n vectorC ++将向量拆分为n向量的最佳方法
【发布时间】:2017-04-01 02:34:07
【问题描述】:

我在这个向量中有一个std::vector<std::string> 我来自txt 文件的push_back 字符串,像这样:

std::string line;
std::vector<std::string> path;
while(getline(fichier, line))
{    
   path.push_back(line);
}

例如,我想将路径 vector 拆分为 n 个其他 vector 的 10 行。 因此,如果我的vector 的大小为 25,我想要 2 个其他 10 个元素的向量和一个 5 个元素的 vector

最好的方法是什么?

【问题讨论】:

标签: c++ c++11 vector


【解决方案1】:

最好是见仁见智,但您可以执行以下操作(bunch_size10):

for(size_t i = 0; i < strings.size(); i += bunch_size) {
    auto last = std::min(strings.size(), i + bunch_size);
    bunches.emplace_back(strings.begin() + i, strings.begin() + last);
}

demo

如果您的字符串很大并且您想避免复制,您可以使用移动版本:

for(size_t i = 0; i < strings.size(); i += bunch_size) {
    auto last = std::min(strings.size(), i + bunch_size);
    auto index = i / bunch_size;
    auto& vec = bunches[index];
    vec.reserve(last - i);
    move(strings.begin() + i, strings.begin() + last, back_inserter(vec));
}

demo

【讨论】:

    【解决方案2】:

    我提出了一些非常笼统的建议(它适用于不同的容器和不同的类型,在这种情况下复杂性会改变):

    #include <algorithm>
    #include <iterator>
    #include <vector>
    
    template<typename Vector>
    auto split_vector(const Vector& v, unsigned number_lines) {
      using Iterator = typename Vector::const_iterator;
      std::vector<Vector> rtn;
      Iterator it = v.cbegin();
      const Iterator end = v.cend();
    
      while (it != end) {
        Vector v;
        std::back_insert_iterator<Vector> inserter(v);
        const auto num_to_copy = std::min(static_cast<unsigned>(
            std::distance(it, end)), number_lines);
        std::copy(it, it + num_to_copy, inserter);
        rtn.push_back(std::move(v));
        std::advance(it, num_to_copy);
      }
    
      return rtn;
    }
    

    您可以指定要拆分的行数:

    例如:

    int main(int argc, char *argv[]) {
      std::vector<std::string> input_vector = {"First", "Second", "Third"};
      auto vs = split_vector(input_vector, 2);
      return 0;
    }
    

    它将产生两个向量:{"First", "Second"}{"Third"}

    【讨论】:

      【解决方案3】:

      您可以在阅读文件时使用stream iterators 来完成这项工作:

      using packet_t = Packet<5>;
      using filler_t = std::istream_iterator<packet_t>;
      
      std::vector<packet_t> packets{
          filler_t(stream),
          filler_t()
      };
      

      结构Packet声明需要operator&gt;&gt;

      template<size_t size>
      struct Packet
      {
          std::vector<std::string> lines;
      
          friend std::istream& operator>>(std::istream& is, Packet& packet)
          {
              packet.lines.clear();
              std::string line;
              for(size_t i = 0; i < size && std::getline(is, line); ++i)
              {
                  packet.lines.push_back(line);
              }
              if(packet.lines.size() > 0)
              {
                  is.clear();
              }
              return is;
          }
      };
      

      注意,当最后几行的数据包不为空时,流会被清除。

      完整代码:

      #include <iostream>
      #include <iterator>
      #include <sstream>
      #include <vector>
      
      template<size_t size>
      struct Packet
      {
          std::vector<std::string> lines;
      
          friend std::istream& operator>>(std::istream& is, Packet& packet)
          {
              packet.lines.clear();
              std::string line;
              for(size_t i = 0; i < size && std::getline(is, line); ++i)
              {
                  packet.lines.push_back(line);
              }
              if(packet.lines.size() > 0)
              {
                  is.clear();
              }
              return is;
          }
      };
      
      int main()
      {
          std::istringstream stream("1\n2\n3\n4\n5\n6\n7\n");
      
          using packet_t = Packet<5>;
          using filler_t = std::istream_iterator<packet_t>;
      
          std::vector<packet_t> packets{
              filler_t(stream),
              filler_t()
          };
      
          for(auto& packet : packets)
          {
              for(auto& line : packet.lines)
              {
                  std::cout << line << "  ";
              }
              std::cout << std::endl;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-06
        • 1970-01-01
        • 1970-01-01
        • 2013-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-11
        相关资源
        最近更新 更多