在Select上的C#Linq语法中创建新对象

Que*_*n3r 0 c# linq

我有一个Vector2对象列表.我想从每个元素中选择一个值并对这些值进行排序.在那之后,我想获得最低价值.

Vector2 cheapestCellPosition = openCells.Select(x => new {
        Vector2 = x,
        Value = GetCostToTarget(x, targetPosition) + GetCell(x).Cost.GetValueOrDefault()
    })
    .OrderBy(x => x.Value)
    .First();
Run Code Online (Sandbox Code Playgroud)

此代码抛出错误

CS0029 C#无法隐式转换匿名类型:Sym.Vector2 Vector2,int值为Sym.Vector2

我怎样才能解决这个问题?我需要根据当前元素设置Value属性.

Eri*_*ert 5

更新:您正在使用它来实现A-star算法.虽然您使用的方法有效,但如果实现优先级队列,可能会更好; 这样做可以获得显着的性能提升.


目前还不清楚你为什么要首先创建一系列匿名类型的麻烦; 为什么不简单地写:

Vector2 cheapestCellPosition = openCells
  .OrderBy(x => GetCostToTarget(x, targetPosition) + GetCell(x).Cost.GetValueOrDefault())
  .First();
Run Code Online (Sandbox Code Playgroud)

需要注意的是,虽然这是比你写的更有效率,是效率不高,因为它可以.

你真正想要的是一组中最小的项目.不幸的是,这不是标准序列库中提供的操作.

我们来解决这个问题.

我们想写的是:

Vector2 cheapestCellPosition = openCells
  .MinBy(x => GetCostToTarget(x, targetPosition) + GetCell(x).Cost.GetValueOrDefault());
Run Code Online (Sandbox Code Playgroud)

让我们假设成本是双倍的,以使其更容易.

static class Extensions 
{
  public static T MinBy(this IEnumerable<T> items, Func<T, double> cost) 
  {
    T minItem = default(T);
    double? minCost = null;
    foreach(T item in items) 
    {
      double current = cost(item);
      if (minCost == null || current < minCost)
      {
        minCost = current;
        minItem = item;
      }
    }
    if (minCost == null) throw InvalidOperationException();
    return minItem;
  }
}
Run Code Online (Sandbox Code Playgroud)

我们已经完成了.我们不必对列表进行排序以找到最小的项目!

练习:假设成本函数不返回double.你能MinBy进一步泛化,以便它可以承担任何成本函数吗?