C++之,我是如何解决数据处理与函数对象运用难题的
在C++编程的征程中,我遇到过形形色色的挑战,其中数据处理与函数对象运用方面的问题,让我花费了不少精力去攻克。今天,就和大家分享一下我的经历。
在一个项目里,我负责处理大量的数值数据,涉及各种数学运算和条件判断。比如,有一组表示商品价格的数据,我需要对这些价格进行不同的计算和筛选。一开始,我用普通的函数和循环来实现这些功能。就像计算每个商品价格的折扣价,代码大概是这样:
#include <iostream>
#include <vector>
std::vector<double> calculateDiscountPrices(const std::vector<double>& prices, double discountRate) {
std::vector<double> discountedPrices;
for (double price : prices) {
discountedPrices.push_back(price * (1 - discountRate));
}
return discountedPrices;
}
int main() {
std::vector<double> prices = {10.0, 20.0, 30.0, 40.0};
double discountRate = 0.2;
std::vector<double> discountedPrices = calculateDiscountPrices(prices, discountRate);
for (double discountedPrice : discountedPrices) {
std::cout << discountedPrice << " ";
}
return 0;
}
虽然这段代码能算出折扣价,但随着需求的增加,问题就来了。如果还需要对价格进行其他运算,像加上税费、进行价格比较等,每次都要写新的循环和逻辑,代码变得又长又不好维护。而且,当需要对多个数据集合进行相同操作时,代码的复用性很差。
为了解决这些问题,我开始寻找更高效、灵活的方法。在学习C++的过程中,我发现了函数对象和标准库算法的强大之处。就拿前面计算折扣价的功能来说,我可以用transform
算法和函数对象来实现:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
class DiscountCalculator {
private:
double discountRate;
public:
DiscountCalculator(double rate) : discountRate(rate) {}
double operator()(double price) {
return price * (1 - discountRate);
}
};
int main() {
std::vector<double> prices = {10.0, 20.0, 30.0, 40.0};
double discountRate = 0.2;
std::vector<double> discountedPrices(prices.size());
std::transform(prices.begin(), prices.end(), discountedPrices.begin(), DiscountCalculator(discountRate));
for (double discountedPrice : discountedPrices) {
std::cout << discountedPrice << " ";
}
return 0;
}
通过这种方式,代码变得简洁了许多。transform
算法会自动遍历prices
向量中的每个元素,并将DiscountCalculator
函数对象应用到每个元素上,得到折扣后的价格。而且,函数对象还可以很方便地在其他地方复用,如果需要对另一组价格数据进行相同的折扣计算,直接使用DiscountCalculator
就行。
解决了基本运算的问题后,我又遇到了新的挑战。在数据处理中,经常需要根据不同的条件对数据进行筛选。比如,筛选出价格大于某个阈值的商品。之前用普通函数实现时,代码是这样的:
#include <iostream>
#include <vector>
std::vector<double> filterPrices(const std::vector<double>& prices, double threshold) {
std::vector<double> filteredPrices;
for (double price : prices) {
if (price > threshold) {
filteredPrices.push_back(price);
}
}
return filteredPrices;
}
int main() {
std::vector<double> prices = {10.0, 20.0, 30.0, 40.0};
double threshold = 25.0;
std::vector<double> filteredPrices = filterPrices(prices, threshold);
for (double filteredPrice : filteredPrices) {
std::cout << filteredPrice << " ";
}
return 0;
}
但这种方式不够灵活,如果筛选条件变复杂,比如既要价格大于阈值,又要满足其他条件,代码就会变得很复杂。
后来,我了解到可以用函数对象和标准库算法来优化这个过程。以筛选价格大于阈值为例,可以这样写:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
class PriceGreaterThan {
private:
double threshold;
public:
PriceGreaterThan(double val) : threshold(val) {}
bool operator()(double price) {
return price > threshold;
}
};
int main() {
std::vector<double> prices = {10.0, 20.0, 30.0, 40.0};
double threshold = 25.0;
std::vector<double> filteredPrices;
std::copy_if(prices.begin(), prices.end(), std::back_inserter(filteredPrices), PriceGreaterThan(threshold));
for (double filteredPrice : filteredPrices) {
std::cout << filteredPrice << " ";
}
return 0;
}
这里使用了copy_if
算法和PriceGreaterThan
函数对象。copy_if
会根据PriceGreaterThan
函数对象的返回值,将满足条件的价格复制到filteredPrices
向量中。如果有更复杂的筛选条件,还可以通过组合多个函数对象来实现。比如,筛选价格大于阈值且小于另一个值的商品:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
class PriceGreaterThan {
private:
double threshold;
public:
PriceGreaterThan(double val) : threshold(val) {}
bool operator()(double price) {
return price > threshold;
}
};
class PriceLessThan {
private:
double upperLimit;
public:
PriceLessThan(double val) : upperLimit(val) {}
bool operator()(double price) {
return price < upperLimit;
}
};
int main() {
std::vector<double> prices = {10.0, 20.0, 30.0, 40.0};
double lowerThreshold = 25.0;
double upperThreshold = 35.0;
std::vector<double> filteredPrices;
auto combinedFilter = [&](double price) {
PriceGreaterThan greaterThanFilter(lowerThreshold);
PriceLessThan lessThanFilter(upperThreshold);
return greaterThanFilter(price) && lessThanFilter(price);
};
std::copy_if(prices.begin(), prices.end(), std::back_inserter(filteredPrices), combinedFilter);
for (double filteredPrice : filteredPrices) {
std::cout << filteredPrice << " ";
}
return 0;
}
通过这种方式,代码的灵活性大大提高,而且逻辑更加清晰。
在使用函数对象的过程中,我还遇到了一些与函数对象适配相关的问题。有时候,需要将已有的函数对象进行调整,以满足特定的需求。比如,我有一个二元函数对象用于比较两个数的大小,但在某些情况下,需要将它转换为一元函数对象,只比较其中一个数和固定值的大小。一开始,我不知道该怎么实现,后来学习到了函数对象适配器的知识。以将比较函数对象转换为例,可以用bind1st
或bind2nd
来实现:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main() {
std::vector<int> numbers = {10, 20, 30, 40};
int fixedValue = 25;
std::vector<int> filteredNumbers;
auto greaterThanFixedValue = std::bind2nd(std::greater<int>(), fixedValue);
std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(filteredNumbers), greaterThanFixedValue);
for (int filteredNumber : filteredNumbers) {
std::cout << filteredNumber << " ";
}
return 0;
}
bind2nd
将std::greater<int>()
的第二个参数绑定为fixedValue
,从而创建了一个一元函数对象greaterThanFixedValue
,可以直接用于copy_if
算法进行筛选。
通过不断地学习和实践,我逐渐掌握了数据处理和函数对象运用的技巧,解决了一个又一个难题。这些经验让我在C++编程的道路上走得更加顺畅。
写作不易,如果这篇文章对你有所帮助,希望你能关注我的博客,点赞并留下你的评论。你的支持是我创作的最大动力,也欢迎大家在评论区分享自己在C++开发中的经验和遇到的问题,让我们一起交流进步!
标签:难题,std,double,price,C++,prices,vector,数据处理,include From: https://blog.csdn.net/wj_rdk/article/details/145955838