不使用 IComparable查找最大/最小元素
假设我有以下内容:
public Class BooClass
{
public int field1;
public double field2;
public DateTime field3;
}
public List<BooClass> booList;
例如,如何使用 booList.Find() 获取 field3 中最早时间的元素
编辑抱歉,为了简化示例,我的意思是公开所有字段。我知道可以在 linq 中做到这一点,我想知道 Find 方法是否有一个简单的单行条件。
Say I have the following:
public Class BooClass
{
public int field1;
public double field2;
public DateTime field3;
}
public List<BooClass> booList;
So for example how do I get the element with the earliest time in field3 using booList.Find()
Edit Apologies, I meant to make all the fields public for simplicity of the example. I know can do it in linq, I wondered if there is a simple single line condition for the Find method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
F# 有方便的
minBy
和maxBy
运算符,我喜欢将其实现为 C# 扩展方法,因为 Linq 库省略了它们。这是一项工作,但只是一点点,它允许您避免复杂的表达式,例如相反,您可以输入以下内容:
一个简单的实现:
这也比顶部的复杂表达式更有效,因为 MinBy 迭代序列恰好一次,而表达式迭代多次且小于或等于两次。当然,排序然后取出第一项需要排序,这是 O(n log n),而这只是 O(n)。
正如 Saeed Amiri 所指出的,如果您依赖 Linq to SQL 或任何其他
IQueryable
提供程序,则此方法不起作用。 (更准确地说,它工作效率低下,因为它从数据库中提取对象并在本地处理它们。)有关不执行此操作的解决方案,请参阅 赛义德的回答。您还可以基于该方法创建一个扩展方法,但由于我现在正在使用手机,因此我将把实现保留为众所周知的“读者练习”。
F# has handy
minBy
andmaxBy
operators, which I like to implement as C# extension methods, since the Linq library omits them. It's a bit of work, but only a bit, and it allows you to avoid complex expressions such asInstead, you can type this:
A simple implementation:
This is also somewhat more efficient than the complex expression at the top, since MinBy iterates the sequence exactly once, while the expression iterates more than once and less than or equal to twice. And, of course, sorting and then taking the first item requires sorting, which is O(n log n), while this is just O(n).
As noted by Saeed Amiri, this approach doesn't work if you are relying on Linq to SQL or any other
IQueryable<>
provider. (More precisely, it works inefficiently because it pulls the objects from the database and works on them locally.) For a solution that doesn't do this, see Saeed's answer.You could also make an extension method based on that approach, but as I am on my phone at the moment I'll leave the implementation as the proverbial "exercise for the reader."
您需要通过公共属性公开 field3(我们将其称为
Field3
),但您可以使用以下内容:查看
Enumerable.First
和Enumerable.Min
注意:这的时间复杂度为 O(n^2)(二次方时间),因为它通过以下方式遍历列表每次迭代
Min
。与 Saeed Amiri 的答案,运行时间为 O(n)(线性时间)。You'll need to expose field3 through through a public property (we'll call it
Field3
), but you could use this:Take a look at
Enumerable.First
andEnumerable.Min
NOTE: That this has a time complexity of O(n^2) (quadratic time) because it is traversing the list via
Min
each iteration. A large enough collection will see serious performance issues compared to Saeed Amiri's answer, which runs in O(n) (linear time).使用 OrderBy 然后获取第一个元素
Use OrderBy Then get the first element
O(n) 方法如下。首先找到最小日期(对于 field3),然后找到具有此最小日期的第一个对象:
只需将您的属性公开即可。
The O(n) approach is as follows. First find min date (for field3), then find first object with this min date:
Just make your property public.
据我所知,仅使用
List.Find
无法检索具有最小日期的 BooClass 对象。当然你可以这样做:(就像 Saeed 的解决方案一样 - 时间复杂度也为 O(n)),但我想这会被认为是作弊......
As far as I can tell, there is no way to retrieve the BooClass object with the minimal date by just using
List<T>.Find
. Of course you can do this:(which - just like Saeed's solution - also has O(n) time complexity), but I guess that would be considered cheating...
如果您不想定义
MinBy
方法,则可以使用聚合,如下所示:要支持空列表,请使用 null 为聚合播种,如下所示:
此解决方案的时间复杂度为 O(n)
If you don't want to define a
MinBy
method, you can use aggregate like so:To support empty lists, seed the aggregate with null, like so:
This solution is O(n)