Steffen_dd
Steffen_dd

Reputation: 69

Q: Sort a List of objects by an inner List with Linq

I have an ELementList and each element has an diagrammList with several diagram’s.

I want to select all elements which has a diagram with the searchname into its diagrammList. (this works) But I want also sort these List by the Layername.

Is the a way to do this?

Thanks

namespace ConsoleLinq
{
    using System.Collections.ObjectModel;
    using System.Linq;
    class Program
    {
        static void Main(string[] args)
        {
            Collection<ElementBase> ELementList = new Collection<ElementBase>();
            ElementBase elementObjekt = new ElementBase { Name = "Node1" };
            elementObjekt.DiagramListe.Add(new Diagram { Name = "Diagram1", LayerName = "Layer2" });
            elementObjekt.DiagramListe.Add(new Diagram { Name = "Diagram2", LayerName = "Layer1" });
            ELementList.Add(elementObjekt);
            elementObjekt = new ElementBase { Name = "Node2" };
            elementObjekt.DiagramListe.Add(new Diagram { Name = "Diagram1", LayerName = "Layer1" });
            ELementList.Add(elementObjekt);
            elementObjekt = new ElementBase { Name = "Node3" };
            elementObjekt.DiagramListe.Add(new Diagram { Name = "Diagram2", LayerName = "Layer1" });
            ELementList.Add(elementObjekt);

            // is there a way to select any item in ELementList which are "Diagram1" and sort the items by LayerName?
            var searchList = (from item in ELementList
                          where item.DiagramListe.GetDiagram("Diagram1") != null
                          select item).ToList();
            // output should
            // searchList[0].Name = "Node2";
            // searchList[1].Name = "Node1";

            foreach (var item in searchList) item.DoSomething();
        }
    }

    public class ElementBase
    {
        public string Name { get; set; }

        public DiagramListe DiagramListe = new DiagramListe();

        public void DoSomething() { }
    }

    public class DiagramListe : Collection<Diagram>
    {
        public Diagram GetDiagram(string diagramName)
            => (from obj in this
                where obj.Name == diagramName
                select obj).FirstOrDefault();
    }

    public class Diagram
    {
        public string Name { get; set; }
        public string LayerName { get; set; }
    }

}

Upvotes: 1

Views: 181

Answers (1)

Georg Patscheider
Georg Patscheider

Reputation: 9463

You can Select into an anonymous object that also contains the LayerName in addition to the ElementBase, then use OrderBy to sort these anonymous objects by LayerName, then Select again to get the ElementBase back out of the anonymous objects.

var diagramNameSearchInput = "Diagram1"
var searchList = 
    (    from item in ELementList
         // put diagram into a variable so we call GetDiagram() only once per element
         let matchingDiagram = item.DiagramListe.GetDiagram(diagramNameSearchInput) 
         where matchingDiagram != null
         select new { // create anonymous object with all properties we need
             BaseItem = item,
             LayerName = matchingDiagram.LayerName
         }
    )
    .OrderBy(a => a.LayerName) // sort anonymous objects
    .Select(a => a.BaseItem)   // result list will contain ElementBase elements
    .ToList();

C# Fiddle for this example.

Upvotes: 1

Related Questions