Home > Software design >  Merge 2 Different List with order condition in C# Linq
Merge 2 Different List with order condition in C# Linq

Time:11-12

So I want to join from 2 different list without any key and order that list some condition.

I have Class like this:

public class DataA
{
    public string Data { get; set; }
    public int Order { get; set; }
    public DateTime CreatedOn { get; set; }
}

public class DataB
{
    public string Data { get; set; }
    public int Order { get; set; }
    public DateTime CreatedOn { get; set; }
}

And the list like this:

var listDataA = new List<DataA> 
{ 
    new DataA { Data = "data a 1", Order = 1, CreatedOn = new DateTime(2020, 11, 12, 00, 00, 00) },
    new DataA { Data = "data a 2", Order = 2, CreatedOn = new DateTime(2020, 11, 13, 00, 00, 00) },
    new DataA { Data = "data a 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 16, 00, 00) },
    new DataA { Data = "data a 6", Order = 6, CreatedOn = new DateTime(2020, 11, 15, 00, 00, 00) },
    new DataA { Data = "data a 7", Order = 7, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) }
};

var listDataB = new List<DataB> 
{
    new DataB { Data = "data b 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 14, 00, 00) },
    new DataB { Data = "data b 8", Order = 8, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) }
};

I want to order the list from each other Order property, if the Order value is the same it will check the CreatedOn property. so the data will look like this:

[
    { Data = "data a 1", Order = 1, CreatedOn = new DateTime(2020, 11, 12, 00, 00, 00) },
    { Data = "data a 2", Order = 2, CreatedOn = new DateTime(2020, 11, 13, 00, 00, 00) },
    { Data = "data b 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 14, 00, 00) },
    { Data = "data a 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 16, 00, 00) },
    { Data = "data a 6", Order = 6, CreatedOn = new DateTime(2020, 11, 15, 00, 00, 00) },
    { Data = "data a 7", Order = 7, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) },
    { Data = "data b 8", Order = 8, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) }
]

How can I do this in Linq?

CodePudding user response:

Really, i think you'd be better off defining an interface for these classes that mentions the common parts you want to use

interface IDataX
{
   int Order { get; set; }
   DateTime CreatedOn { get; set; }
}

public class DataA: IDataX ...

public class DataB: IDataX ...

Then you could do like

var output = listDataA.Cast<IDataX>().Concat(listDataB).OrderBy(d => d.Order).ThenBy(d => d.CreatedOn);

as Data is common to both, you could add that to the interface too, and then you could use Data from IDataX without having to know specifically whether the object underneath is a DataA or a DataB.


If you're against that (and also against a similar idea of having a parent class for A/B that has the common properties Order/Created..), you might have to project to some common holder (which could equally be anonymous but presented here as not for sake of example):

class Holder{
   public int Order { get; set; }
   public DateTime CreatedOn { get; set; }

   public object OriginalData { get; set; }
}

And concat projections..

listA
  .Select(a => new Holder { Order = a.Order, CreatedOn = a.CreatedOn, OriginalData = a})
  .Concat(
     listB.Select(b => new Holder { Order = b.Order, CreatedOn = b.CreatedOn, OriginalData = b})
  ).OrderBy(x => x.Order).ThenBy(x => x.CreatedOn)

..then cast back the OriginalData when you want to use it.. (if(x.OriginalData is DataA a) ... else if(x.OriginalData is DataB b) which is a bit.. ugh)

Personally, I'd definitely be leveraging some kind of polymorphism for this

  • Related