Sno*_*owy 32 c# linq listview object
我有一个List,MyStuff有一个Type Float属性.
有些对象的属性值为10,20,22,30.
我需要编写一个查找最接近21的对象的查询,在这种情况下,它会找到20和22对象.然后我需要编写一个发现对象接近21而不会过去的东西,它会返回值为20的对象.
我不知道在哪里/如何开始这个.救命?
谢谢.
更新 - 哇这里有很多很棒的回复.谢谢!我不知道应该遵循哪一个,所以我会尝试一下.有一点可能使这个更多(或更少)有趣的是同一个查询将必须应用于LINQ-to-SQL实体,所以从MS Linq论坛收集的答案可能会发挥最佳作用?不知道.
amu*_*rra 24
尝试按数字和21之间的差值的绝对值对它们进行排序,然后取第一项:
float closest = MyStuff
.Select (n => new { n, distance = Math.Abs (n - 21) })
.OrderBy (p => p.distance)
.First().n;
Run Code Online (Sandbox Code Playgroud)
或根据@Yuriy Faktorovich的评论缩短它:
float closest = MyStuff
.OrderBy(n => Math.Abs(n - 21))
.First();
Run Code Online (Sandbox Code Playgroud)
Ani*_*Ani 22
这是一个满足线性时间内第二个查询的解决方案:
var pivot = 21f;
var closestBelow = pivot - numbers.Where(n => n <= pivot)
.Min(n => pivot - n);
Run Code Online (Sandbox Code Playgroud)
(澄清后从"上方"编辑到"下方")
至于第一个查询,这将是最容易使用MoreLinq
的MinBy
扩展:
var closest = numbers.MinBy(n => Math.Abs(pivot - n));
Run Code Online (Sandbox Code Playgroud)
它也可以在标准LINQ中以线性时间进行,但是有2次传递:
var minDistance = numbers.Min(n => Math.Abs(pivot - n));
var closest = numbers.First(n => Math.Abs(pivot - n) == minDistance);
Run Code Online (Sandbox Code Playgroud)
如果效率不是问题,您可以对序列进行排序并选择O(n * log n)
其他人发布的第一个值.
基于Microsoft Linq论坛上的这篇文章:
var numbers = new List<float> { 10f, 20f, 22f, 30f };
var target = 21f;
//gets single number which is closest
var closest = numbers.Select( n => new { n, distance = Math.Abs( n - target ) } )
.OrderBy( p => p.distance )
.First().n;
//get two closest
var take = 2;
var closests = numbers.Select( n => new { n, distance = Math.Abs( n - target ) } )
.OrderBy( p => p.distance )
.Select( p => p.n )
.Take( take );
//gets any that are within x of target
var within = 1;
var withins = numbers.Select( n => new { n, distance = Math.Abs( n - target ) } )
.Where( p => p.distance <= within )
.Select( p => p.n );
Run Code Online (Sandbox Code Playgroud)