当我需要对列表进行复杂搜索时,linq表达式对我来说很复杂。
假设我有列表
public class Object {
var length;
var height;
var depth;
}
如何按最大长度过滤对象id,如果有多个索引,则按最大宽度过滤,如果有多个索引,则按最大深度过滤,如果有多个索引,则首先返回最大索引。
我发现了最大值:
float maxWidth = boxes.Max(x => x.width);
float maxHeight = boxes.Max(x => x.height);
float maxDepth = boxes.Max(x => x.depth);
然后我用于循环获取值。没关系,但是在每个循环之后,我必须创建另一个列表以获取另一个值,等等。
private GameObject largestSurfaceBox()
{
//find max length.width, height box
float maxWidth = boxes.Max(x => x.GetComponent<Box>().dimensions.x);
List<GameObject> maxWidthBoxes = new List<GameObject>();
for (int i = 0; i < boxes.Count; i++) {
if (System.Math.Abs(boxes[i].GetComponent<Box>().dimensions.x - maxWidth) < float.Epsilon) {
maxWidthBoxes.Add(boxes[i]);
}
}
float maxHeight = maxWidthBoxes.Max(x => x.GetComponent<Box>().dimensions.y);
List<GameObject> maxHeightBoxes = new List<GameObject>();
for (int i = 0; i < maxWidthBoxes.Count; i++) {
if (System.Math.Abs(maxWidthBoxes[i].GetComponent<Box>().dimensions.y - maxHeight) < float.Epsilon) {
maxHeightBoxes.Add(boxes[i]);
}
}
List<GameObject> maxDepthBoxes = new List<GameObject>();
float maxDepth = maxHeightBoxes.Max(x => x.GetComponent<Box>().dimensions.z);
for (int i = 0; i < maxHeightBoxes.Count; i++) {
if (System.Math.Abs(maxHeightBoxes[i].GetComponent<Box>().dimensions.z - maxDepth) < float.Epsilon) {
maxDepthBoxes.Add(boxes[i]);
}
}
return maxDepthBoxes[0];
}
如果可能的话,如何使用if语句来完成这种优雅的linq方法?
答案 0 :(得分:0)
听起来像您在寻找具有多个条件的“ MaxBy”。使用LINQ扩展的选项很少。最简单,可能是效率最低的就是订购并获得第一个或最后一个项目:
GameObject result = boxes.OrderBy(x => x.width)
.ThenBy(x => x.height)
.ThenBy(x => x.depth)
.LastOrDefault();
另一种选择是在您的课程上实现custom comparer,以便您可以只进行boxes.Max()
,
或使用已经实现它的类,例如Tuple
(如果collection为空,则导致Exception):
GameObject result = boxes.Max(x => Tuple.Create(x.width, x.height, x.depth, x)).Item4;
上面的方法也不是最有效的,因为它为每个项目创建一个Tuple
,但是可能足够快。最有效的应该是一个for
循环,以在不使用LINQ的情况下获得最多的商品。