按属性搜索一组无序的对象并返回相应的对象
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 来查看 Ingredient
的 Name
成员。
并且您需要将结果保存在一个变量中,以便返回时使用。
也许是这样的:
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.
通过 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 来查看 Ingredient
的 Name
成员。
并且您需要将结果保存在一个变量中,以便返回时使用。
也许是这样的:
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.