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



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

我的方法可以吗?或者我只使用unordered_set<Ingredient> ingredients就可以实现吗?

按照我的方法,我如何在FindIngredient函数中返回?我想返回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 ???
}

} 
}

如果你不介意较慢的搜索算法(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::unordereded_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.

您可以将std::find_if与合适的lambda函数一起使用,以使用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;
}

最新更新