Search code examples
c#linqasp.net-coreienumerable

how to get specific collection from a collection with linq?


I want to get all Form objects below the root as a list

    public class Root
    {
        public int recordsTotal { get; set; }
        public int recordsFiltered { get; set; }
        public List<Datum> Data { get; set; }
        public int ResultCode { get; set; }
    }

    public class Datum
    {
        public DateTime StartDate { get; set; }
        public DateTime StopDate { get; set; }
        public List<Evaluation> Evaluations { get; set; }
    }

    public class Evaluation
    {
        public string Evaluator { get; set; }
        public string EvaluatorUserId { get; set; }
        public Form Form { get; set; }
        public DateTime EvaluationDate { get; set; }
        public string EvaluationId { get; set; }
    }

I'm trying to get it with linq but haven't succeeded yet


Solution

  • Short answer based on my understanding of this:

    var forms = root.Data
        .SelectMany(datum => datum.Evaluations)
        .Select(evaluation => evaluation.Form)
        .ToList();
    

    Long answer with test

    You don't specify class Form, hence I tested with this minimum code:

    using System.Collections.Generic;
    
    namespace XUnitTestProject.StackOverflow
    {
        public class Root
        {
            public List<Datum> Data { get; set; }
        }
    
        public class Datum
        {
            public List<Evaluation> Evaluations { get; set; }
        }
    
        public class Form
        {
            public string Name { get; set; }
        }
    
        public class Evaluation
        {
            public Form Form { get; set; }
        }
    }
    

    And a test class

    using System.Collections.Generic;
    using System.Linq;
    using Xunit;
    
    namespace XUnitTestProject.StackOverflow
    {
        public class LinqTests
        {
            [Fact]
            public void Test()
            {
                var forms = CreateValidRoot().Data
                    .SelectMany(datum => datum.Evaluations)
                    .Select(evaluation => evaluation.Form)
                    .ToList();
    
                Assert.Equal(2, forms.Count);
                Assert.Equal("~form1~", forms[0].Name);
                Assert.Equal("~form2~", forms[1].Name);
            }
    
            private static Root CreateValidRoot() => new()
            {
                Data = new List<Datum>
                {
                    new()
                    {
                        Evaluations = new List<Evaluation>
                        {
                            new() {Form = new Form{Name = "~form1~"}}
                        }
                    },
                    new()
                    {
                        Evaluations = new List<Evaluation>
                        {
                            new() {Form = new Form{Name = "~form2~"}}
                        }
                    }
                }
            };
        }
    }