【问题标题】:Selecting the begin() and end() for C++为 C++ 选择 begin() 和 end()
【发布时间】:2018-02-13 12:16:15
【问题描述】:

我有一个项目要求我按特定列从 .csv 文件读取值并对其进行排序。 我在 C++ 中使用算法库,即#include <algorithm> 该库具有我计划使用的功能sort()。 它要求我指定开始和结束,例如,对于一个名为 vect 的 2d 向量,它需要 vect.begin()vect.end()。 我的问题是,是否可以为 sort() 函数指定确切的开始位置和结束位置。这就像从 vect[1][0] 开始并在 vect[9][9] 结束。

感谢您的帮助

【问题讨论】:

  • 你不能std::sort 2D 向量/数组。你希望这样做会有什么结果?
  • 如果vect.begin()是向量的第一个元素(假设它不为空),那么你认为vect.begin() + 1是什么?
  • 对列进行间接排序,然后使用索引访问行。在此处查看示例:stackoverflow.com/questions/48764471/…
  • @HolyBlackCat 好吧,当我根据一列对值进行排序时,它确实有效,尽管它也将表格的标题移到了底部,这就是我试图避免的
  • @HolyBlackCat :当然你可以对二维向量进行排序。向量的排序向量的自然定义是结果具有按字典顺序存储的内部向量(因此 [[4, 5, 6], [1, 2, 3], [1, 2, 4]] 将是输出为 [[1, 2, 3], [1, 2, 4], [4, 5, 6]])。当然,实际上,std::vector 没有定义 operator <。无论如何,OP 都需要一个客户比较函子来选择列。

标签: c++


【解决方案1】:

为了便于讨论,我假设您正在使用std::vector<std::vector<int> >。同样的讨论也适用于其他类型的二维向量。

如果您想对单个 ints 进行排序,以便它们在 std::vector<std::vector<int> > 中排序,则无法直接进行。没有可以直接从 std::vector<std::vector<int>> 获得的迭代器,它运行在所有嵌套的 ints 上。

一种方法可能是在std::vector<int> 中设置一个临时副本(即创建一个扁平的一维向量),对其进行排序,然后将元素复制回来。例如;

 std::vector<std:vector<int> > vec;

   // populate vec somehow

 std::vector<int> elements(0);

 // create a single std::vector<int> from the vector<vector<int>> by
 //    appending the vector<int>s end to end

 for (const auto &row : vec)
 {
      elements.insert(elements.end(), row.begin(), row.end());
 }

 std::sort(elements.begin(), elements.end());   // sort in ascending order

 //   now copy the sorted elements back

 auto start = elements.begin();

 for (auto &row : vec)   //  non-const here since we seek to change the vector<int>s within vec
 {
      auto end = start + row.size();
      std::copy(start, end, row.begin());
      start = end;
 }

最后一个循环中row.size()row.begin() 的恶作剧处理了vec 中的vector&lt;int&gt; 大小不同的可能性,因此会发生变化

 {{5,6,7}, {1,2}, {3,4,8}}

成为

 {{1,2,3}, {4, 5}, {6,7,8}}

而不是其他东西,例如

 {{1,2}, {3,4,5}, {6, 7, 8}};     //   vector<int>s resized

如果您假设所有内部向量的大小相同,则可以稍微简化一下。

或者,您可以尝试手动滚动 struct/class 类型,该类型具有随机访问迭代器的所有属性(这是 std::sort() 所要求的)。该结构(或其成员函数/运算符)将需要同时跟踪 std::vector&lt;int&gt;(在 2D 向量内)和它所引用的该向量内的特定 int。这将是相当棘手的(例如,如果自定义迭代器引用特定 std::vector&lt;int&gt; 的最后一个元素,递增它必须给出引用下一个 vector&lt;int&gt; 的第一个元素的结果)。 std::vector&lt;std::vector&lt;int&gt; &gt; 根本没有任何内置功能可以直接为您提供这样的迭代器。我将滚动这样一个自定义迭代器作为练习。

【讨论】:

    【解决方案2】:

    鉴于您知道迭代的顺序,您可以指定相对于开始的元素。

    vect.begin()     // first element
    vect.begin() + 2 // third element
    

    因此,如果您只想对第一个元素进行排序,比如说 10 个元素,请使用以下内容:

    std::sort(vect.begin(), vect.begin() + 10);
    

    更多here.

    正如其他人已经提到的,您不能真正对 2D 矢量进行排序。因此,您要么单独对每个向量进行排序,要么将其展平为 1D 向量并使用索引计算进行 2D 解释。

    【讨论】:

    • 那么,考虑到我想防止列标题和行号不被排序,我将如何将 2D 向量展平为 1D 并将其带回 2D。我使用了sort(vect.begin() + 1, vect.end()),它阻止了对列名进行排序,但仍然对行号进行排序。
      谢谢
    • 您不想一直切换数据布局。我想到的是例如如果您有一个 NxN 矩阵,则将其存储在大小为 NxN 的一维向量 v 中。要访问位置 i/j 处的元素,您将使用 v[i * N + j]。如果这不符合您的想法,可以提供您拥有的矩阵以及您希望如何对其进行排序的示例。
    【解决方案3】:
    1. 将排序依据的列加载到std::vector&lt; std::pair &gt; index; 并设置
      • 作为向量行索引的第一个元素 (0,1,2,...)
      • 第二个元素将是行和列中的值
    2. 使用此问题按配对的第二项对其进行排序:How do I sort a vector of pairs based on the second element of the pair?
    3. 现在您有了按向量 中的列值排序的行索引,您可以创建新的二维向量并使用原始二维向量中的行填充其行。在每次迭代中,使用index 向量中的第一项选择原始二维向量中具有索引的行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-19
      • 1970-01-01
      • 2014-03-18
      • 2013-09-06
      • 2019-05-18
      • 2020-10-14
      相关资源
      最近更新 更多