如何更改向量中元素的值?

Posted

技术标签:

【中文标题】如何更改向量中元素的值?【英文标题】: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 的问题。 【参考方案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 和其他地方讨论的许多原因,这更好,但这里有两个主要原因:

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

第 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;

【讨论】:

以上是关于如何更改向量中元素的值?的主要内容,如果未能解决你的问题,请参考以下文章

在几个可变 lambda 中更改相同的向量

如何更改此向量函数以接受更多元素? [复制]

如何在不更改其参考的情况下将更改应用于张量/向量的元素?

如何通过将向量元素传递给函数来更改它们

设置者不更改类中向量的数据

指针向量:为啥在外部更改指针不会更改向量元素?