Search code examples
c#linq

IGrouping with nested properties


I have a IDictionary<Key,Mesh>, where Mesh contains a IEnumerable<Vertex>. Vertex is a struct and contains a VectorInt3 that represents the World Position.

I want to write a function/query that groups all vertex indices of a all meshes by the world position. I.e. I want all vertex indices, grouped by Mesh that share the same world position

I tried the following:

var vertexMeshGroups = meshes.Values.GroupBy(mesh => mesh.Vertices.Select((RoomVertex vertex,int idx) => (vertex,idx))
                                                                  .GroupBy(ele => ele.vertex.WorldPosition));

but that results in a IGrouping<IEnumerable<IGrouping<VectorInt3,(Vertex, int)>>,Mesh>,
when I would want something more like a IGrouping<VectorInt3,IGrouping<Mesh,int>>

How would I achieve this? The structs and class look like this:

public class Mesh
{
    public List<Vertex> Vertices = new List<Vertex>();

    public Mesh()
    {
    }
}

public struct Vertex
{
    public VectorInt3 WorldPosition;
}

Solution

  • How about this kind of code:

    var vertexMeshGroups = meshes.Values
        .SelectMany(mesh => mesh.Vertices.Select(vertex => (vertex, mesh))
        .GroupBy(pair => pair.vertex.WorldPosition, pair.mesh);
    

    This is written here online, so maybe it contains some error, but let me explain the idea:

    A mesh contains multiple vertices. Due to that reason a mesh can have multiple positions, which means a mesh can be within multiple groups if you group by the world position. So in a first step you have to create a tuple or pair for each world position that also knows its parent mesh element. When this pair is available you can group these pairs by the desired child property WorldPosition and take the parent element mesh as value element of the grouping.