C#,使用Linq通过多种条件从List获取对象索引

时间:2018-11-28 12:47:28

标签: c# list linq

当我需要对列表进行复杂搜索时,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方法?

1 个答案:

答案 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的情况下获得最多的商品。