linq如何访问变量

时间:2017-03-15 16:57:42

标签: c# unity3d

我很擅长使用linq。我的目标是列表的元素(vector3s)具有属性x和z,并且想要找到x或z值相同的2个vector3元素的平均值。例如,如果你有一个地板,它有4个顶点a,b,c,d,其中a是topleft角,b是顶角,c是左下角,d是右下角。我想找到ab,cd,bd,ac之间的中间点。我实际上有一个字典,其中一个游戏对象楼层在vector3列表中有相应的顶点。到目前为止,这将解释我的代码。

Dictionary<GameObject, List<Vector3>> floorVertices = new Dictionary<GameObject, List<Vector3>>();
List<Vector3> vertices = new List<Vector3>();

verticeMidpoints = (
        from l in floorVertices.Values 
        from v in l 
        where l.Any(v2 => v2.x == v.x || v2.z == v.z) 
        select (new Vector3((v.x + v2.x) / 2), 
                            (v.y + v2.y) / 2, 
                            (v.z + v2.z) / 2);
    ).ToList(); 

继承代码以找到顶点。

// the floor has 8 vertices and I would like the bottom ones that touch the ground
vertices = (
        from v in vertices 
        where v.y < ((  from v2 in vertices 
                        select v2.y
                      ).Average()) 
        select v
    ).ToList(); 

我如何调整(无法访问v2的地方)

verticeMidpoints = (
        from l in floorVertices.Values 
        from v in l 
        where l.Any(v2 => v2.x == v.x || v2.z == v.z) 
        select (new Vector3((v.x + v2.x) / 2), 
                            (v.y + v2.y) / 2, 
                            (v.z + v2.z) / 2)
    ).ToList();

让它发挥作用。

我很确定找到顶点的代码有更多代码需要。 请帮忙

2 个答案:

答案 0 :(得分:1)

就像我在评论中所说的那样,精心设计的LINQ查询可以使代码干净简洁,对性能影响很小或没有影响,但除非您对LINQ知识有信心,否则应尽可能避免执行速度为一个主要问题(就像游戏编程一样)。

相反,您应该使用辅助方法和常规循环来获取您之后的内容:

获取顶点:

public List<Vector3> GetFloorVertices(List<Vector3> vertices)
{
    // Preallocate memory for the list so we don't 
    // need to worry about reallocating on insertions
    List<Vector3> floorVerts = new List<Vector3>(vertices.Count);
    float avg = vertices.Average(v => v.y);

    for (int i = 0; i < vertices.Count; i++)
    {
        if (vertices[i].y < avg)
        {
            floorVerts.Add(vertices[i]);
        }
    }

    return floorVerts;
}

获得中点:

public List<Vector3> GetMidpoints(List<Vector3> vertices)
{
    // Preallocate memory for the list so we don't 
    // need to worry about reallocating on insertions
    List<Vector3> midpoints = new List<Vector3>(vertices.Count * vertices.Count);

    for (int i = 0; i < vertices.Count; i++)
    {
        for (int j = 0; j < vertices.Count; j++)
        {
            if (vertices[i].x != vertices[j].x && vertices[i].z != vertices[j].z)
                continue;

            midpoints.Add(new Vector3(
                            (vertices[i].x + vertices[j].x) / 2,
                            (vertices[i].y + vertices[j].y) / 2,
                            (vertices[i].z + vertices[j].z) / 2
            ));
        }
    }

    return midpoints;
}

答案 1 :(得分:0)

查看let条款

这样的事情 verticeMidpoints = ( from l in floorVertices.Values from v in l let v2 = ....... ).ToList();