Home > Net >  how to filter list in c# using linq
how to filter list in c# using linq

Time:02-19

i am working on a ticket where there is a array of data i am passing as parameter to a method and based on the parameter and another date parameter i want filtered result but i am not able to get that result

here is my code

public void Test1()
        {
            // Arrange
            var first = new Level
            {
                Code = "P3",
                Date= DateTime.Parse("01 March 2022")
            };
            var second = new Level
            {
                Code = "P3",
                Date= DateTime.Parse("01 April 2022")
            };
            var firstbrk = new Level
            {
                Code = "B1",
                Date = DateTime.Parse("01 March 2022")
            };
            var secondbrk = new Level
            {
                Code = "B1",
                Date= DateTime.Parse("01 April 2022")
            };
            var data = new[]
            {
                first ,
                second,
                firstbrk,
                secondbrk
            };

            // Act
            var main = Handler.GetExtras(data, DateTime.Parse("02 April 2022"));

            // Assert
            CollectionAssert.AreEquivalent(main , new[] { second, secondbrk });
        }
        
        [Test]
        public void Test2()
        {
            // Arrange
            var first= new Level
            {
                Code = "A3",
                Date= DateTime.Parse("01 March 2022")
            };
            var second= new Level
            {
                Code = "A3",
                Date= DateTime.Parse("01 April 2022")
            };
            var firstbrk= new Level
            {
                Code = "B1",
                Date = DateTime.Parse("01 March 2022")
            };
            var secondbrk = new Level
            {
                Code = "B1",
                Date= DateTime.Parse("01 April 2022")
            };
            var data= new[]
            {
                second,
                first,
                sceondbrk,
                firstbrk
            };

            // Act
            var main = Handler.GetExtras(data, DateTime.Parse("02 April 2022"));

            // Assert
            CollectionAssert.AreEquivalent(main, new[] { second, secondbrk });
        }

Here is handler code

  public static IEnumerable<Extra> GetExtras(IEnumerable<Extra> main, DateTime idate)
        {
           
            return main.GroupBy(x => x.Code).Select(x => x.LastOrDefault(x => x.Date< idate));
          
        }

Here in handler code the issue is only test1 is satisfying test2 is not working because of LastOrDefault used

i want the the input which is supplier to handler method should be first filtered based on Code

so with every code it should get the data and then with that it should check that Date from the class Extra should be less than idate and then only latest date from the group of that particular code should get picked

e.g if date is 2 March 2022 and 2 April 2022 for code T3

and date is 5 march 2022 and 1 April 2022 for code B1 and i date is 5 April

so for code T3 2 April should get picked and for code B1 1 April Should get picked

also if input is sent in incorrect order like Test case Test2 then it should order the input in proper order and then do above stuff

Thanks in advance for help

CodePudding user response:

you have to fix GetExtras method since your class name Level, not Extra And you can not group your data , it will be the same

public static IEnumerable<Level> GetExtras(IEnumerable<Level> main, DateTime idate)
{
    return main.Where(x => x.Date < idate).OrderByDescending(x => x.Date).Take(1);
}

if you still want to group you can use this code, but result will be the same

public static IEnumerable<Level> GetExtras(IEnumerable<Level> main, DateTime idate)
{
    return main.GroupBy(x => new { x.Code, x.Date }).Where(x => x.Key.Date < idate)
    .Select( x=> new Level {Code= x.Key.Code, Date= x.Key.Date}).OrderByDescending(x => x.Date).Take(1);
}

CodePudding user response:

This looks extremely similar to this question, except that here you want the one entry that matches the criteria for each Code. I am reusing logic from the answer that I gave for the other question here, but using .GroupBy() to group by Code:

public static IEnumerable<Extra> FetchExtras(Extra[] lvl, DateTime idate)
{
    return lvl
        .GroupBy(extra => extra.Code)
        .Select(gr => gr.Where(x => x.Date < idate).MaxBy(x => x.Date));
}

.MaxBy() is available from System.Linq from .Net 6.

  • Related