C# 如何在不进行广泛搜索的情况下基于2个条件获取对象?
很难将其概括为一行问题。我有一门课是这样的:C# 如何在不进行广泛搜索的情况下基于2个条件获取对象?,c#,.net,linq,collections,C#,.net,Linq,Collections,很难将其概括为一行问题。我有一门课是这样的: class Item { int Count {get; set;} double Value {get; set;} } 以及包含任意数量的项值的列表 如何获得项的计数最低,值最高 性能并不重要,但优雅是重要的,因为我不希望有巨大的嵌套循环来执行此操作,除非没有优雅的方式,如Linq等 编辑: 以下是可能包含以下项的示例列表: {Count, Value} {2, 10}, {6, 60}, {5, 21}, {4, 65},
class Item
{
int Count {get; set;}
double Value {get; set;}
}
以及包含任意数量的项
值的列表
如何获得项的计数最低,值最高
性能并不重要,但优雅是重要的,因为我不希望有巨大的嵌套循环来执行此操作,除非没有优雅的方式,如Linq等
编辑:
以下是可能包含以下项的示例列表:
{Count, Value}
{2, 10}, {6, 60}, {5, 21}, {4, 65}, {2, 35}, {4, 18}, {3, 55}, {7, 99}, {2, 25}
所以这里我想要的值是{2,35}
,因为它在所有项目中的计数最低,对于具有相同计数
值的项目,它的值最高
好的,现在我们有点清楚了:
只要它具有最低计数,该范围内的最高值就可以
这很容易
var best = list.OrderBy(x => x.Count)
.ThenByDescending(x => x.Value)
.FirstOrDefault();
如果列表为空,则将给出null
,否则将给出计数最低的项,如果该计数有多个,则给出值最高的项
这比它可能的效率要低,因为我们可以通过创建一个比较器来比较任意两个值,从而在一次过程中真正做到这一点——但这肯定是一种在最少的代码中获得正确元素的方法。希望它现在可以工作,遗憾的是它没有Jon的那么优雅
var res = (from i in items
orderby i.Count ascending, i.Value descending
select i).FirstOrDefault();
使用(具有MinBy
和MaxBy
运算符),您可以在线性时间内轻松完成此操作(遗憾的是需要额外的过程):
编辑:
这里有一种(丑陋的)方法,可以使用标准LINQ在O(1)空间和O(n)时间内一次通过:
var minCountItemWithMaxValue = items.Aggregate(
(bestSoFar, next) =>
(next.Count < bestSoFar.Count) ? next :
(next.Count > bestSoFar.Count) ? bestSoFar :
(next.Value > bestSoFar.Value) ? next : bestSoFar);
var minCountItemWithMaxValue=items.Aggregate(
(最佳,下一个)=>
(next.CountbestSoFar.Count)?bestSoFar:
(next.Value>bestSoFar.Value)?next:bestSoFar);
您想取回两个项目,一个是计数最低的项目,另一个是值最高的项目,还是只想返回一个计数最低且来自此项目的值最高的项目?这两个查询是分开的吗?也,它必须是一个列表
,还是您愿意维护一个专门构建的数据结构,以便在需要时高效地执行所需的查询?@BigL:对不起,我指的是一个计数最低但值最高的项目。
@Joan:如果计数最低的项目不是具有最高价值?还是这是一个多目标优化?@Ani:我使用了一个列表
,但我不确定你的意思。你是说像IEnumerable这样的东西?我想这可能没什么大不了的。谢谢乔恩,这正是我想要的。你所说的比较器是指,在项
类中?@JoanVenge:要么制作项
实现IComparer
/IComparer
,要么提供一个单独的IComparer
传递给最大值
或最小值
方法。谢谢Jon,顺便说一句,如果我有IComparer
,那只是出于好奇,我是否可以使用Min
,并得到相同的结果?只是好奇。我们真的需要一个带有链式比较的MaxBy
。。。但这很难表达。我必须考虑一下。。。(我确实提到了Myelnq,但觉得在这种情况下是不值得的。)乔恩:<代码> Almin Buy < /Cord>和<代码> AlxMax B/C>比较容易,是吗?它不是理想的,因为您必须保留所有当前具有最小值的项的列表。因此,保持O(1)内存方面是很好的。我确信使用另一个界面是可行的,但是否值得付出努力则是另一回事。@Jon:Btw,“MoreLINQ”而不是“MoreLINQ”是你首选的大写字母吗?我使用“morelinq”是因为这就是它在项目页面上的资本化方式。@Jon:当然,但由于它们是不同的扩展(没有必要去掉O(1)
spaceMinBy
和MaxBy
),客户端必须明确要求它接受O(n)
空格命中。这不起作用。你明白为什么吗?仔细比较你的答案和乔恩的答案。
var minCountItemWithMaxValue = items.AllMinBy(item => item.Count)
.MaxBy(item => item.Value);
var minCountItemWithMaxValue = items.Aggregate(
(bestSoFar, next) =>
(next.Count < bestSoFar.Count) ? next :
(next.Count > bestSoFar.Count) ? bestSoFar :
(next.Value > bestSoFar.Value) ? next : bestSoFar);