使用 lambda 函数在 C++ 中按然后排序
Posted
技术标签:
【中文标题】使用 lambda 函数在 C++ 中按然后排序【英文标题】:sort by and then in c++ using lambda functions 【发布时间】:2018-01-10 08:15:27 【问题描述】:在 C# 中给定一个结构:
struct Point int x, int y
我们可以这样写:
List<Point> list;
list.OrderBy(p => p.x).ThenBy(q => q.y);
如何使用 lambda 函数在 C++ 中表达这种逻辑?
【问题讨论】:
所以你想按x
排序,然后按y
?
@GauravSehgal 是的。
【参考方案1】:
看起来你也想对(y, x)
1 进行字典排序。您可以利用库函数std::tie
。那个返回一个引用元组,std::tuple
有一个小于运算符来执行字典比较。因此,您只需指定要比较项目的顺序。
这是 std::vector
的外观(您在 C++ 中转到容器类型,始终以 std::vector
开头):
std::vector<Point> my_list;
// Fill my_list
std::sort(begin(my_list), end(my_list), [](auto const& l, auto const& r)
return std::tie(l.y, l.x) < std::tie(r.y, r.x);
);
1 - 我只是基于方法名称,所以这可能不是你真正想要的。
【讨论】:
Python 列表比链表更类似于 C++ 向量。 @n.m.- C# 列表呢? OP基于此询问。我自己对 C# 不太熟悉。 根据here,显然是一样的…… @Aconcagua - 相应地修改了答案。谢谢! 我的错,错误地假设了 Python,但显然 C# 列表也更像向量。【参考方案2】:您可以使用 STL 函数 std::sort。示例:
struct point
int x;
int y;
;
// Compare function. This can be lambda function too.
bool comp(const point& a,const point& b)
if(a.x > b.x) return true;
else if(a.x == b.x) return a.y > b.y;
return false;
int main()
// v is vector (or any other container which can be iterated) containing points
std::sort(v.begin(),v.end(),comp);
【讨论】:
你就是这样按x排序的。我猜你应该加If(a.x==b.x) return a.y>b.y;
。
是的。我刚刚写了一些虚拟比较函数。但为了清楚起见,我会根据您的建议添加代码。
((a.x > b.x) and (a.y > b.y))
是错误且危险的比较,不适合排序。
@n.m.如果你能解释一下什么时候会出错,那就太好了。
考虑a.x > b.x
,但a.y < b.y
的情况。您的函数将为 comp(a, b)
和 comp(b, a)
返回 false,这表明 a
和 b
应该被视为相等。但他们显然不应该。【参考方案3】:
两种方式 - 要么排序两次,首先按 y,然后对 x 使用 stable 排序(请注意,这与 C# 中的完全相反!)。 std::sort
运气不好,虽然它不稳定,但幸运的是,正如 Benjamin 暗示的那样,还有 std::stable_sort
...
另一种方法是确保两个点进行比较,从而首先应用 x 的差异,并且仅在相等的情况下才考虑 y:
std::sort
(
// range to sort
list.begin(), list.end(),
// next the comparator - you wanted a lambda? OK, here it is:
[](point const& a, point const& b)
return a.x < b.x || a.x == b.x && a.y < b.y;
);
【讨论】:
std::sort
可能不稳定,但标准库中还有另一个功能。奇怪地命名为std::stable_sort
。
@BenjaminLindley 感谢您的提示。第一种方法并没有应付太多,因为我认为第二种方法更胜一筹......【参考方案4】:
您只需将 lambda 函数指定为 std::list::sort()
。您决定要如何排序。
list.sort([](Point i,Point j)
if(i.x!=j.x)
return i.x<j.x;
else
return i.y<j.y;
);
【讨论】:
你最好用const Point &
@user2807083 实际上没有,在这种情况下 Point 在 x64 系统上是 sizeof == 8,所以复制它比使用引用更好以上是关于使用 lambda 函数在 C++ 中按然后排序的主要内容,如果未能解决你的问题,请参考以下文章