【问题标题】:How can I change the value of the elements in a vector?如何更改向量中元素的值?
【发布时间】:2011-01-26 17:25:00
【问题描述】:

我有这段代码,它从文件中读取输入并将其存储在向量中。到目前为止,我已经得到它给我向量内的值的总和,并使用总和给出值的平均值。

我现在想做的是学习如何再次访问向量并从向量的每个元素中减去一个值,然后再次打印出来。例如,一旦计算了总和和平均值,我希望能够重新打印终端中的每个值减去平均值。有什么建议/例子吗?

#include <iostream>
#include <vector>
#include <fstream>
#include <cmath>

using namespace std;

int main()
{
    fstream input;
    input.open("input.txt");
    double d;
    vector<double> v;
    cout << "The values in the file input.txt are: " << endl;
    while (input >> d)
    {
        cout << d << endl;
        v.push_back(d);
    }

double total = 0.0;
double mean = 0.0;
double sub = 0.0;
for (int i = 0; i < v.size(); i++)
{
    total += v[i];
    mean = total / v.size();
    sub = v[i] -= mean;
}
cout << "The sum of the values is: " << total << endl;
cout << "The mean value is: " << mean << endl;
cout << sub << endl;
}

【问题讨论】:

  • 你已经写了 sub = v[i] -= mean。 v[i] -= mean 与 v[i] = v[i] - mean 相同。所以你已经在修改数组元素了!
  • "有什么建议/例子吗?" 是的,我的建议是阅读一个很好的文档来源,比如 cppreference,其中包含大量例子对于这样简单的请求,不需要或没有用关于 SO 的问题。

标签: c++ vector


【解决方案1】:

您可以像数组一样简单地访问它,即v[i] = v[i] - some_num;

【讨论】:

  • 我已经尝试在我的 for 循环中执行此操作,但它只返回向量中的最后一个元素 - 数字。我怎样才能让它通过并对向量中的所有元素进行处理?
  • 是的,只是对最后一个块的一个小改动,我在上面的代码中改了。
  • @Meursault:但是你的循环是错误的,只有从最后一个元素中减去正确的平均值,从所有其他元素中减去的平均值是错误的,因为你的 total 不正确。这是您面临的问题吗?
  • 您需要两个循环:第一个循环将总和累加到“总计”中,然后可以计算平均值(一次,不在循环内),然后在第二个循环中减去计算的“每个元素的意思。
【解决方案2】:

嗯,你总是可以对向量进行变换:

std::transform(v.begin(), v.end(), v.begin(), [mean](int i) -> int { return i - mean; });

你也可以设计一个迭代器适配器,当它被取消引用时,它返回一个操作的结果,该操作应用于它的组件迭代器的取消引用。然后您可以将向量复制到输出流:

std::copy(adapter(v.begin(), [mean](int i) -> { return i - mean; }), v.end(), std::ostream_iterator<int>(cout, "\n"));

或者,您可以使用 for 循环……但这有点无聊。

【讨论】:

    【解决方案3】:

    您可以像访问任何其他数组一样访问向量中的值。

    for (int i = 0; i < v.size(); i++)
    {         
      v[i] -= 1;         
    } 
    

    【讨论】:

      【解决方案4】:

      您的代码运行良好。当我运行它时,我得到了输出:

      The values in the file input.txt are:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      The sum of the values is: 55
      The mean value is: 5.5
      

      但它仍然可以改进。

      您正在使用索引对向量进行迭代。这不是“STL 方式”——也就是说,您应该使用迭代器:

      typedef vector<double> doubles;
      for( doubles::const_iterator it = v.begin(), it_end = v.end(); it != it_end; ++it )
      {
          total += *it;
          mean = total / v.size();
      }
      

      由于here 和其他地方讨论的许多原因,这更好,但这里有两个主要原因:

      1. 每个容器都提供iterator 概念。并非每个容器都提供随机访问(例如,索引访问)。
      2. 您可以概括您的迭代代码。

      第 2 点提出了另一种改进代码的方法。关于你的代码的另一件事不是很像 STL,那就是使用了手写循环。 &lt;algorithm&gt;s 就是为此目的而设计的,最好的代码是你从未编写过的代码。您可以通过使用累加器使用循环来计算向量的总和和均值:

      #include <numeric>
      #include <functional>
      struct my_totals : public std::binary_function<my_totals, double, my_totals>
      {
          my_totals() : total_(0), count_(0) {};
          my_totals operator+(double v) const
          {
              my_totals ret = *this;
              ret.total_ += v;
              ++ret.count_;
              return ret;
          }
          double mean() const { return total_/count_; }
          double total_;
          unsigned count_;
      };
      

      ...然后:

      my_totals ttls = std::accumulate(v.begin(), v.end(), my_totals());
      cout << "The sum of the values is: " << ttls.total_ << endl;
      cout << "The mean value is: " << ttls.mean() << endl;
      

      编辑:

      如果您受益于符合 C++0x 的编译器,则可以使用std::for_each(在#include &lt;algorithm&gt; 内)和lambda expression 使这更简单:

      double total = 0;
      for_each( v.begin(), v.end(), [&total](double  v) { total += v; });
      cout << "The sum of the values is: " << total << endl;
      cout << "The mean value is: " << total/v.size() << endl;
      

      【讨论】:

      • 使用 for_each+lambda 来做积累的目的不是很 STLish。 double total = std::accumulate(v.begin(),v.end(),0.0);
      • @Kleist:是的。这是一种权衡。
      【解决方案5】:

      只需使用:

      for (int i = 0; i < v.size(); i++)
      {
          v[i] -= valueToSubstract;
      }
      

      或者它的等价物(并且更具可读性?):

      for (int i = 0; i < v.size(); i++)
          v[i] = v[i] - valueToSubstract;
      

      【讨论】:

        【解决方案6】:

        您可能需要考虑使用一些算法:

        // read in the data:
        std::copy(std::istream_iterator<double>(input), 
                  std::istream_iterator<double>(),
                  std::back_inserter(v));
        
        sum = std::accumulate(v.begin(), v.end(), 0);
        average = sum / v.size();
        

        您可以使用std::transform 修改这些值,但在我们得到 lambda 表达式 (C++0x) 之前,它可能比它的价值更麻烦:

        class difference { 
            double base;
        public:
            difference(double b) : base(b) {}
            double operator()(double v) { return v-base; }
        };
        
        std::transform(v.begin(), v.end(), v.begin(), difference(average));
        

        【讨论】:

          【解决方案7】:
          int main() {
            using namespace std;
          
            fstream input ("input.txt");
            if (!input) return 1;
          
            vector<double> v;
            for (double d; input >> d;) {
              v.push_back(d);
            }
            if (v.empty()) return 1;
          
            double total = std::accumulate(v.begin(), v.end(), 0.0);
            double mean = total / v.size();
          
            cout << "The values in the file input.txt are:\n";
            for (vector<double>::const_iterator x = v.begin(); x != v.end(); ++x) {
              cout << *x << '\n';
            }
            cout << "The sum of the values is: " << total << '\n';
            cout << "The mean value is: " << mean << '\n';
            cout << "After subtracting the mean, The values are:\n";
            for (vector<double>::const_iterator x = v.begin(); x != v.end(); ++x) {
              cout << *x - mean << '\n';  // outputs without changing
              *x -= mean;  // changes the values in the vector
            }
          
            return 0;
          }
          

          【讨论】:

            猜你喜欢
            • 2011-02-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-15
            • 1970-01-01
            • 2011-02-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多