LINQ 获取最接近的值?

发布于 2024-09-19 07:59:06 字数 328 浏览 5 评论 0原文

我有一个列表,MyStuff 有一个 Float 类型的属性。

有些对象的属性值为 10、20、22、30。

我需要编写一个查询来查找最接近 21 的对象,在本例中它将找到 20 和 22 对象。然后我需要编写一个发现对象接近 21 而不会超过的对象,并且它将返回值为 20 的对象

。我不知道从哪里/如何开始这个。帮助?

谢谢。

更新 - 哇这里有这么多很棒的回复。谢谢!我不知道该遵循哪一个,所以我会尝试所有的。可能使这变得更(或更少)有趣的是,相同的查询必须适用于 LINQ-to-SQL 实体,因此从 MS Linq 论坛获得的答案可能效果最好?不知道。

I have a List, MyStuff has a property of Type Float.

There are objects with property values of 10,20,22,30.

I need to write a query that finds the objects closest to 21, in this case it would find the 20 and 22 object. Then I need to write one that finds the object closes to 21 without going over, and it would return the object with a value of 20.

I have no idea where/how to begin with this one. Help?

Thanks.

Update - wow there are so many awesome responses here. Thanks! I don't know which one to follow so I will try them all. One thing that might make this more (or less) interesting is that the same query will have to apply to LINQ-to-SQL entities, so possibly the answer harvested from the MS Linq forums will work the best? Don't know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧情勿念 2024-09-26 07:59:06

尝试按数字与 21 之间的差的绝对值对它们进行排序,然后取第一项:

float closest = MyStuff
    .Select (n => new { n, distance = Math.Abs (n - 21) })
    .OrderBy (p => p.distance)
    .First().n;

或者根据 @Yuriy Faktorovich 的评论缩短它:

float closest = MyStuff
    .OrderBy(n => Math.Abs(n - 21))
    .First();

Try sorting them by the absolute value of the difference between the number and 21 and then take the first item:

float closest = MyStuff
    .Select (n => new { n, distance = Math.Abs (n - 21) })
    .OrderBy (p => p.distance)
    .First().n;

Or shorten it according to @Yuriy Faktorovich's comment:

float closest = MyStuff
    .OrderBy(n => Math.Abs(n - 21))
    .First();
只等公子 2024-09-26 07:59:06

这是在线性时间内满足第二个查询的解决方案:(

var pivot = 21f;
var closestBelow = pivot - numbers.Where(n => n <= pivot)
                                  .Min(n => pivot - n);

澄清后从“上方”编辑为“下方”)

至于第一个查询,最简单的是使用 MoreLinqMinBy 扩展:

var closest = numbers.MinBy(n => Math.Abs(pivot - n));

也可以在标准 LINQ 中以线性时间完成此操作,但需要 2源的传递:

var minDistance = numbers.Min(n => Math.Abs(pivot - n));
var closest = numbers.First(n => Math.Abs(pivot - n) == minDistance);

如果效率不是问题,您可以对序列进行排序并选择 O(n * log n) 中的第一个值,正如其他人发布的那样。

Here's a solution that satisfies the second query in linear time:

var pivot = 21f;
var closestBelow = pivot - numbers.Where(n => n <= pivot)
                                  .Min(n => pivot - n);

(Edited from 'above' to 'below' after clarification)

As for the first query, it would be easiest to use MoreLinq's MinBy extension:

var closest = numbers.MinBy(n => Math.Abs(pivot - n));

It's also possible to do it in standard LINQ in linear time, but with 2 passes of the source:

var minDistance = numbers.Min(n => Math.Abs(pivot - n));
var closest = numbers.First(n => Math.Abs(pivot - n) == minDistance);

If efficiency is not an issue, you could sort the sequence and pick the first value in O(n * log n) as others have posted.

手心的海 2024-09-26 07:59:06

基于这篇文章 在 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 );

Based on this post at the Microsoft Linq forums:

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 );
姐不稀罕 2024-09-26 07:59:06
List<float> numbers = new List<float>() { 10f, 20f, 22f, 30f };
float pivot = 21f;
var result = numbers.Where(x => x >= pivot).OrderBy(x => x).FirstOrDefault();

或者

var result = (from n in numbers
              where n>=pivot
              orderby n
              select n).FirstOrDefault();

,这里有一个扩展方法:

public static T Closest<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, TKey pivot) where TKey : IComparable<TKey>
{
    return source.Where(x => pivot.CompareTo(keySelector(x)) <= 0).OrderBy(keySelector).FirstOrDefault();
}

用法:

var result = numbers.Closest(n => n, pivot);
List<float> numbers = new List<float>() { 10f, 20f, 22f, 30f };
float pivot = 21f;
var result = numbers.Where(x => x >= pivot).OrderBy(x => x).FirstOrDefault();

OR

var result = (from n in numbers
              where n>=pivot
              orderby n
              select n).FirstOrDefault();

and here comes an extension method:

public static T Closest<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, TKey pivot) where TKey : IComparable<TKey>
{
    return source.Where(x => pivot.CompareTo(keySelector(x)) <= 0).OrderBy(keySelector).FirstOrDefault();
}

Usage:

var result = numbers.Closest(n => n, pivot);
埋葬我深情 2024-09-26 07:59:06

从.net 6开始可以使用 MinBy为了以与投票最多的帖子类似的方式实现结果。它现在是标准 Linq 的一部分。
用法:

float closest = MyStuff.MinBy(x => Math.Abs(x - 21));

Since .net 6 MinBy can be used in order to achieve the result in similar manner as in the most upvoted post. It's now a part of standard Linq.
usage:

float closest = MyStuff.MinBy(x => Math.Abs(x - 21));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文