如何按给定字段对结构的向量进行分类?
我需要按给定字段对结构向量进行排序。
给任何面临同样问题的人: 我只是制作了自己的排序功能,在那里您可以根据需要在lambda中传递(不仅有两个变量)。
在这里,我使用了lambda表达式,但是由于Lambda接受仅通过的变量,因此我无法定义要排序的字段。
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.name > b.name; });
我不能这样做:
string sortfield = name;
sort(patients.begin(), patients.end(), [](Patient a, Patient b)
{
if(sortfield == "name") return a.name < b.name;
else if(sortfield == "age") return a.age < b.age;
...
});
- 因为它会导致错误,因为lambda只能使用经过的变量,而不是本地。
- 很难扩展。每次我将新字段添加到结构中时,我都必须回到这里,然后再添加一个“ else”,如果“
我也尝试使用一个指针到功能会员,但它的工作方式相同。
我可以使用这样的开关案例:
enum Fields
{
Name, Gender, DateOfBirth
};
Fields field;
switch (field)
{
case Fields::Name:
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.name > b.name; });
break;
case Fields::Gender:
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.gender > b.gender; });
break;
case Fields::DateOfBirth:
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.dateOfBirth > b.dateOfBirth; });
break;
default:
break;
}
但是它将破坏OCP(打开封闭的原理)。当结构将扩展时,我将不得不回来几次以添加更多“情况”块。
有更好的方法吗?
I need to sort vector of structures by a given field.
To anyone who faces the same problem:
I just made my own sort function and there you can pass in lambda as many variables as you want(not only two of them).
Here I used a lambda expression, but I can't define the field to sort by as lambda accepts only passed variables.
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.name > b.name; });
I can't do it just like this:
string sortfield = name;
sort(patients.begin(), patients.end(), [](Patient a, Patient b)
{
if(sortfield == "name") return a.name < b.name;
else if(sortfield == "age") return a.age < b.age;
...
});
- Because it will cause an error as lambda can use only passed variables, not local.
- It will be hard to expand. Each time when I will add new field to the structure, I will have to go back here and add one more "else if"
I also tried to use a pointer to a function-member, but it works the same way.
I could use switch-case like this:
enum Fields
{
Name, Gender, DateOfBirth
};
Fields field;
switch (field)
{
case Fields::Name:
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.name > b.name; });
break;
case Fields::Gender:
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.gender > b.gender; });
break;
case Fields::DateOfBirth:
sort(patients.begin(), patients.end(), [](Patient a, Patient b) { return a.dateOfBirth > b.dateOfBirth; });
break;
default:
break;
}
but then it will break OCP (Open Closed Principle). I will have to come back several times to add more "case" blocks when the structure will be expanded.
Is there a better way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用另一个lambda选择要比较的字段:
You can use another lambda to pick the field to be compared:
这是错误的。您当然可以利用lambda中的本地变量。 捕获是方形括号的目的。
另一方面,如果修改了
患者
类,此方法确实会增加维护负担。如果将切换逻辑放入类中,则可以将更改本地化为类实现。 (无论您是使用字符串还是枚举取决于您,但请记住,编译器不会在字符串中捕获错别字。)如果您想添加一个新的字段进行排序(但不是如果您添加了一个新成员,而无需选择对其进行排序)。但是,此代码与类实现有关,因此至少您不必在代码库中狩猎即可找到更新的位置。
在执行分类的代码中使用此问题:
特殊情况下,如果所有潜在的排序字段具有相同的类型(对于患者而言不太可能,但对于其他情况),并且公共(在许多情况下不建议使用),然后可以使用带指针到成员的lambda代替
sortby
方法。这种方法的好处是,修改课程时没有特殊的维护。限制是,由于限制(相同类型和公众),通常不是一个选择。我想,如果您使用指针来成员函数,则可以将“公共”限制得到解决。相同类型的限制可能仍然是一个障碍,语法更加混乱。
在这一点上,另一个答案中的“另一种lambda”方法可能是可取的(以风格为基础)。
This is wrong. You certainly can make use of local variables in a lambda. Capturing is what the square brackets are for.
On the other hand, this approach does add a maintenance burden if the
Patient
class is modified. You could keep your changes localized to the class implementation if you put the switching logic in the class. (Whether you use a string or an enumeration is up to you, but keep in mind that the compiler will not catch typos in a string.)You will still have to update this if you want to add a new field for sorting (but not if you add a new member without the option to sort on it). However, this code is with the class implementation, so at least you do not have to hunt through your code base to find places to update.
To use this in your code that does the sorting:
As a special case, if all the potential sort fields have the same type (not likely for patients, but possible for other situations) and public (not recommended in many scenarios), then a lambda with a pointer-to-member could be used instead of the
SortBy
method. The benefit of this approach is that there is no special maintenance when the class is modified. The limitation is that it is often not an option due to the restrictions (same type and public).I suppose the "public" restriction can be gotten around if you use pointers to member functions. The same-type restriction might still be an obstacle, and the syntax is messier.
At this point, the "another lambda" approach in the other answer might be preferable (on style grounds).