[英]create new object within C# Linq syntax on Select
我有一个Vector2
对象列表。 我想从每个元素中选择一个值并对这些值进行排序。 在那之后,我想获得最低的价值。
Vector2 cheapestCellPosition = openCells.Select(x => new {
Vector2 = x,
Value = GetCostToTarget(x, targetPosition) + GetCell(x).Cost.GetValueOrDefault()
})
.OrderBy(x => x.Value)
.First();
此代码引发错误
CS0029 C#无法隐式转换匿名类型:Sym.Vector2 Vector2,将int值转换为Sym.Vector2
我怎样才能解决这个问题? 我需要基于当前元素设置Value属性。
更新:您正在使用它来实现A-star算法。 尽管您使用的方法可行,但如果实现优先级队列,您可能会更好。 这样您就可以获得重大的性能胜利。
目前尚不清楚为什么要首先创建一个匿名类型序列。 为什么不简单地写:
Vector2 cheapestCellPosition = openCells
.OrderBy(x => GetCostToTarget(x, targetPosition) + GetCell(x).Cost.GetValueOrDefault())
.First();
?
请注意,尽管这比您写的要有效,但效率却不如可能 。
您真正想要的是集合中最小的项目。 不幸的是,这不是标准序列库中提供的操作。
让我们修复它。
我们要写的是:
Vector2 cheapestCellPosition = openCells
.MinBy(x => GetCostToTarget(x, targetPosition) + GetCell(x).Cost.GetValueOrDefault());
让我们假设成本是它的两倍,使其变得更容易。
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;
}
}
我们完成了。 我们不必对列表进行排序即可找到最小的物品!
练习 :假设cost函数不返回double。 您可以进一步对MinBy
进行泛化,以便采用任何成本函数吗?
在此行之后:
.Select(x => new { Vector2 = x, Value = GetCostToTarget(x, targetPosition) + GetCell(x).Cost.GetValueOrDefault() })
您具有具有Vector2
和Value
属性的匿名对象的集合。 这不是 Vector2
。
最后,当您使用First
您仍将选择那些匿名对象中的第一个 。 它不是Vector2
,所以不能将其分配给Vector2
类型的变量。
但是,如果您将其更改为:
.First().Vector2
这将获取您选择的第一个匿名对象的Vector2
属性。 这是一个Vector2
,因此它应该可分配给cheapestCellPosition
虽然这不是最容易阅读的东西,但是您的错误告诉您:
CS0029 C#无法隐式转换匿名类型:Sym.Vector2 Vector2,将int值转换为Sym.Vector2
它告诉你它无法与转换匿名类型Vector2
类型的财产Sym.Vector2
和Value
类型的财产int
输入Sym.Vector2
问题在于您正在选择同时具有Vector2
属性和Value
属性的匿名类型,但是随后您尝试将第一个属性分配给Vector2
类型。
如果openCells
确实是IEnumerable<Vector2>
,则只需删除Select
并将订购代码直接放在OrderBy
子句中,然后返回First
一个:
Vector2 cheapestCellPosition = openCells
.OrderBy(cell => GetCostToTarget(cell, targetPosition) +
GetCell(cell).Cost.GetValueOrDefault())
.First();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.