如何对存储Food对象shared_ptr的C++向量进行排序?
嘿,我来帮你搞定这个排序问题!首先得明确:因为Food的成员都是私有属性,我们得先给Food类加几个公共的getter方法,这样才能在排序时访问到这些属性。先补全Food类的必要代码:
#include <string> class Food { private: std::string _description; // 食物描述,比如"all-purpose wheat flour" std::string _amount; // 份量描述,比如"1 cup" int _amount_g; // 份量克数,非负 int _calories; // 能量(千卡),你没写完,我先默认补这个成员啦 public: // 假设你已经有合适的构造函数,这里只加getter const std::string& getDescription() const { return _description; } int getAmountG() const { return _amount_g; } int getCalories() const { return _calories; } };
接下来我们用C++标准库的std::sort算法(需要包含<algorithm>头文件),结合lambda表达式(最常用、最灵活的方式)来实现不同需求的排序:
1. 按食物描述的字典序排序
这是最基础的字符串排序,直接比较_description的字典序:
#include <algorithm> #include <vector> #include <memory> std::vector<std::shared_ptr<Food>> foods; // 你的shared_ptr向量 // 按描述升序排列(A-Z) std::sort(foods.begin(), foods.end(), [](const std::shared_ptr<Food>& a, const std::shared_ptr<Food>& b) { // 先处理空指针:把空指针放到向量末尾 if (!a && !b) return false; if (!a) return false; if (!b) return true; return a->getDescription() < b->getDescription(); });
如果要降序(Z-A),把<改成>就行。
2. 按食物重量(_amount_g)排序
按单份食物的克数从小到大/从大到小排序:
// 按重量升序(轻→重) std::sort(foods.begin(), foods.end(), [](const std::shared_ptr<Food>& a, const std::shared_ptr<Food>& b) { if (!a && !b) return false; if (!a) return false; if (!b) return true; return a->getAmountG() < b->getAmountG(); }); // 按重量降序(重→轻),只需要把比较符号反过来 std::sort(foods.begin(), foods.end(), [](const std::shared_ptr<Food>& a, const std::shared_ptr<Food>& b) { if (!a && !b) return false; if (!a) return false; if (!b) return true; return a->getAmountG() > b->getAmountG(); });
3. 按能量(卡路里)排序
这里分两种场景:一种是按单份食物的总卡路里,另一种是更实用的**每100克卡路里(能量密度)**排序:
// 场景1:按单份总卡路里升序 std::sort(foods.begin(), foods.end(), [](const std::shared_ptr<Food>& a, const std::shared_ptr<Food>& b) { if (!a && !b) return false; if (!a) return false; if (!b) return true; return a->getCalories() < b->getCalories(); }); // 场景2:按每100克卡路里升序(更合理,适合对比不同食物的能量密度) std::sort(foods.begin(), foods.end(), [](const std::shared_ptr<Food>& a, const std::shared_ptr<Food>& b) { if (!a && !b) return false; if (!a) return false; if (!b) return true; // 处理重量为0的情况,避免除以0 if (a->getAmountG() == 0) return false; if (b->getAmountG() == 0) return true; // 计算每100克的卡路里 double calPer100gA = static_cast<double>(a->getCalories()) / a->getAmountG() * 100; double calPer100gB = static_cast<double>(b->getCalories()) / b->getAmountG() * 100; return calPer100gA < calPer100gB; });
4. 复用排序逻辑的进阶写法
如果某个排序规则要多次使用,可以把lambda改成命名函数或者函数对象:
方式1:命名函数
// 定义全局或命名空间内的比较函数 bool compareFoodByDescription(const std::shared_ptr<Food>& a, const std::shared_ptr<Food>& b) { if (!a && !b) return false; if (!a) return false; if (!b) return true; return a->getDescription() < b->getDescription(); } // 调用排序 std::sort(foods.begin(), foods.end(), compareFoodByDescription);
方式2:函数对象(适用于带状态的比较逻辑)
struct CompareFoodByAmountG { bool isDescending; // 可以传入参数控制升序/降序 CompareFoodByAmountG(bool desc = false) : isDescending(desc) {} bool operator()(const std::shared_ptr<Food>& a, const std::shared_ptr<Food>& b) const { if (!a && !b) return false; if (!a) return false; if (!b) return true; if (isDescending) { return a->getAmountG() > b->getAmountG(); } else { return a->getAmountG() < b->getAmountG(); } } }; // 调用:升序排序 std::sort(foods.begin(), foods.end(), CompareFoodByAmountG()); // 调用:降序排序 std::sort(foods.begin(), foods.end(), CompareFoodByAmountG(true));
内容的提问来源于stack exchange,提问作者Rat
相关产品推荐
相关产品推荐

