【问题标题】:formatting vector of int to a string将 int 的向量格式化为字符串
【发布时间】:2021-08-12 10:18:30
【问题描述】:

所以这是一个练习,我必须将std::vector<int> 格式化为std::string。该练习要求我们仅使用 stl 算法,并且不允许使用 for 循环。 std::for_each 是允许的,因为它也是算法的一部分,但他们也不想让我们使用它。

输入总是排序的,并且不包含任何重复。

Input std::vector<int> Output std::string
{ 4, 8, 12} "4, 8, 12"
{ -20, -19, .., .., 10, 11} "[-20, 11]"
{ -5, 8, 9, 10, 11, 12, 21} "-5, [8, 12], 21"
{ -2, 5, 6, 7, 10, 11, 12 } "-2, [5, 7], [10, 12]"

我已经在研究 std::searchstd::adjacent_find 是否可以使用它们,但我认为它们不会满足我的需求。

这是我尝试过的。我也不认为这是解决这个问题的正确方法,因为完整的练习是关于标准算法的,我在这里没有使用任何。任何关于什么 stl 算法在这种情况下可以派上用场的建议,将不胜感激。

std::string FormatLine(int lineNumber)
{
    std::vector<int> input = { -2, 5, 6, 7, 9, 11, 12, 13 };
    
    std::stringstream output{};
    int startNumber { input[0] };
    bool isRange{ false };
    
    for (int i{ 1 }; i < input.size(); ++i)
    {
        const int lastNumber = input[i - 1];
        
        // continue if its a incrementing sequence
        if (input[i] - 1 == lastNumber)
        {
            // if no range has been started yet, start one
            if (!isRange)
            {
                output << "[" << startNumber << ", ";
                isRange = true;
            }
            continue;
        }

        output << lastNumber;
        // if a range was started, close it with the last element of the range
        if (isRange)
        {
            output << "],";
            isRange = false;
        }
        // just a number so add a comment
        else
            output << ", ";
        
        startNumber = input[i];
    }
    // dont forget to add the last element
    output << input.back();
    // if it was still in a range, add closing bracket
    if (isRange) 
        output << ']';
    
    return output.str();
}

【问题讨论】:

  • “练习要求我们只使用 stl 算法”哇,还有希望:)。请展示你的尝试。我们不会为您写作业,但如果您给我们一些工作,我们可以提供帮助。 meta.stackoverflow.com/questions/334822/…
  • 这篇文章能回答你的问题吗? stackoverflow.com/questions/8581832/…
  • @Attis 不,这个问题的重点是将连续范围“压缩”成与非连续部分不同的格式。
  • 一旦连续范围被“压缩”,使用std::copy() 和输出流迭代器可以很容易地处理输出。需要进行一些调整,因为在输出 int(例如从向量)之后,以下字符在某些情况下需要是 ',',而在某些特定情况下需要是其他字符。
  • 如果你已经有一个普通的for 循环,那么尝试将循环体转换为一个只接受一个参数(当前值)的函数。一旦你有了它,你可以用std::for_each调用替换循环。

标签: c++


【解决方案1】:

解决方案不能是简单的单循环,因为您需要检查后面的元素才能知道当前元素是否以[ 为前缀。因此我建议做一些预处理。

当数字连续时,任务要求按间隔对数字进行分组。要在代码中反映这一点,请使用结构:

 struct interval {
      int start;
      int size;          
 };

单个数字也可以表示为interval,大小为0。现在您可以使用单次遍历向量来填充std::vector&lt;interval&gt;

我喜欢只使用标准算法的前提,但排除循环支持std::for_each 有点愚蠢,因为在某种意义上,基于范围的循环是整个容器迭代时的现代for_each

 std::vector<interval> intervals;
 intervals.emplace_back(input[0],0);
 std::for_each( input.begin()+1,input.end(),[&invervals](int x){
      // check if x == intervals.back().start + intervals.back().size + 1
      // to decide if the last intervals size must be incremented
      // or a new interval be added
 });

一旦你得到那个向量,你只需要另一个循环来构建所需的字符串。当interval.size == 1 没有[ 前缀,否则interval.start+interval.size-1 ] 也被附加。

可能会有一些错误,但我希望你能明白。

【讨论】:

    【解决方案2】:

    积累呢? https://godbolt.org/z/xfK8acrT8

        std::array arr{1, 2, 3, 4, 5, 6};
        auto begin = arr.begin(), end = arr.end();
        
        std::string r;
        if (begin != end)
            r = std::to_string(*begin++);
        r = std::accumulate(begin, end, r, [](std::string result, int value) { result += ", " + std::to_string(value); return result; });
        std::printf("%s", r.c_str());```
    

    产量:

    1, 2, 3, 4, 5, 6
    

    【讨论】:

      【解决方案3】:

      我建议:

      #include <iostream>
      #include <vector>
      #include <string>
      #include <algorithm>
      
      using namespace std;
      
      string get_string_expression(vector<int> & vec)
      {
          int pre_iter = vec[0] - 2;
          vector<vector<int>> inter_result;
      
          sort(vec.begin(), vec.end());
          for_each(vec.begin(), vec.end(), [&inter_result, &pre_iter](int iter) {     
              if (iter - pre_iter == 1)
              {
                  inter_result.rbegin()->push_back(iter);
              }
              else
              {
                  vector<int> temp = { iter };
                  inter_result.push_back(temp);
              }       
              pre_iter = iter;
          });
      
          string result = "";
          for_each(inter_result.begin(), inter_result.end(), [&result](vector<int> iter) {
              if (iter.size() == 1)
              {
                  result += to_string(iter[0]);
              }
              else
              {
                  result += (string("[") + to_string(*iter.begin()) + "," + to_string(*iter.rbegin()) + "]");
              }
              result += ", ";
          });
      
          return result.substr(0, result.length() - 2);
      }
      
      int main()
      {
          vector<int> input_1 = { 4, 8, 12 };
          vector<int> input_2(32);
          vector<int> input_3 = { -5, 8, 9, 10, 11, 12, 21 };
          vector<int> input_4 = { -2, 5, 6, 7, 10, 11, 12 };
      
          //. initialize input_2
          generate(input_2.begin(), input_2.end(), [n = -20]()mutable{ return n++; });
      
          cout << "input_1: " << get_string_expression(input_1) << endl;
          cout << "input_2: " << get_string_expression(input_2) << endl;
          cout << "input_3: " << get_string_expression(input_3) << endl;
          cout << "input_4: " << get_string_expression(input_4) << endl;
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-07
        • 1970-01-01
        • 1970-01-01
        • 2014-01-06
        • 2016-01-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多