按属性搜索一组无序的对象并返回相应的对象

Searching an unordered set of objects by attribute and returning the corresponding object

通过 Ingredient.name 搜索时,我需要 FindIngredient 到 return 一个 const Ingredient &。我需要使用 unordered_set。所以我想我需要其中的 2 个来包含对象,另一个只包含字符串属性 name 以便按字符串搜索。

我的方法是否可行,或者我是否可以仅使用 unordered_set<Ingredient> ingredients 来实现它?

按照我的方法,我如何在 FindIngredient 函数中 return ?我想 return ingredients 中的对象,其属性名称是在 ingredientsByName

中搜索到的对象
      class Ingredient {
    public:
      string Name;
      int Price;
      string Description;
  };

class Pizzeria {
          unordered_set<string> ingredientsByName; 
          unordered_set<Ingredient> ingredients;
    public:
    
    void AddIngredient(const string &name, const string &description, const int &price)
        { 
            if(ingredientsByName.find(name) == ingredients.end())
            {
               throw "Ingredient already inserted";
            }
            else
            {
               Ingredient ingredient;
               ingredient.Name = name;
               ingredient.Price = price;
               ingredient.Description = description;
               ingredients.insert(ingredient); 
               ingredientsByName.insert(ingredient.Name);
               ingredients.insert(ingredient);       
            }             
        }
        
        const Ingredient &FindIngredient(const string &name) const 
        { 
            if(ingredientsByName.find(name) == ingredients.end())
            {
               throw "Ingredient not found";
            }
            else
            {
                return //  how Do I return  the corresponding Ingredient ???
            }
        
        } 
    }

您可以使用 std::find_if with a suitable lambda function 来查看 IngredientName 成员。

并且您需要将结果保存在一个变量中,以便返回时使用。

也许是这样的:

const Ingredient &FindIngredient(const string &name) const
{
    auto result = std::find_if(begin(ingredients), end(ingredients), [&name](Ingredient const& ingredient)
    {
        return ingredient.Name == name;
    });

    if (result == end(ingredients))
    {
        throw "Ingredient not found";
    }

    return *result;
}

如果您不介意较慢的搜索算法(O(N) 时间),那么您可以做一个简单的循环:

for (auto it = ingredients.begin(); it != ingredients.end(); ++it)
    if (it->Name == name)
        return *it; // Return found ingredient.
throw "Ingredient not found";

上面的循环可以做得更短:

for (auto const & e: ingredients)
    if (e.Name == name)
        return e; // Return found ingredient.
throw "Ingredient not found";

如果您想要快速搜索算法(O(Log N) 时间),那么您可以使用 std::unordered_map 而不是设置,即:

unordered_map<string, Ingredient> ingredientsByName;

添加到地图:

ingredientsByName[ingredient.Name] = ingredient;

然后在里面搜索:

auto it = ingredientsByName.find(name);
if (it == ingredientsByName.end())
    throw "Ingredient not found";
return it->second; // Returns found ingredient.

如果您需要对元素进行排序(按键),那么您可以使用 std::map 而不是 std::unordered_map,map 总是按键排序(但是对于数千个元素,搜索和插入速度慢 2-5 倍),而 unordered_map 始终未排序(但搜索和插入速度快 2-5 倍)。


如果你想单独储存原料,那么你可以使用std::shared_ptr:

unordered_map<string, shared_ptr<Ingredient>> ingredientsByName;
vector<shared_ptr<Ingredient>> ingredients;


// Adding element:

shared_ptr<Ingredient> ingredient = make_shared<Ingredient>();
ingredient->Name = "abc";
// Also fill other fields.

ingredients.push_back(ingredient);
ingredientsByName[ingredient->Name] = ingredient;


// Search:

auto it = ingredientsByName.find(name);
if (it == ingredientsByName.end())
    throw "Ingredient not found";
return *it->second; // Returns found ingredient.