Question

I am using LINQ to generate two separate lists of items. However, I need to merge these two lists in a specific way. I already am sorting by a specific attribute (sequence number) and doing some other magic to ensure that everything is where it should be, but the resulting set is eluding me.

Here is what I have so far:

List<item> list1 = { item1, item2, item3, item7, item8, item11, item12 }
List<item> list2 = { item4, item5, item6, 
                     item4, item5, item6, 
                     item9, item10, 
                     item9, item10 }

The resulting set should look like this:

List<item> listFinal = { item1, item2, item3, 
                         item4, item5, item6, 
                         item4, item5, item6, 
                         item7, item8, 
                         item9, item10, 
                         item9, item10, 
                         item11, item12 }

Essentially, I need the final list to include the repeated items in order regardless of how many sets of repeated items there are. There could be one, many or none.

Is there an easy way to accomplish this using LINQ on the two sets I have? Or would I have to use if statements to concatenate the lists?

Was it helpful?

Solution

Simply use Concat then OrderBy

var resultList = list1.Concat(list2).OrderBy(x => x.Something).ToList();

UPDATE: According to your comments, here is an extension method that you can use.Since you don't tell us how your class look like, I just create a class an interface for example.

public static IEnumerable<T> ConcatItems<T>(this IList<T> source, IList<T> dest)
        where T: ISequence
{
     int index = 0;

     foreach (var x in source)
     {
         if (x.SequenceNumber < dest[index].SequenceNumber)
         {
             dest.Insert(index, x);
             continue;
         }
         while(x.SequenceNumber > dest[index].SequenceNumber) index++;

         if (index != dest.Count - 1 && x.SequenceNumber == dest[index].SequenceNumber)
         {
             while (index != dest.Count -1 && 
                 Math.Abs(dest[index].SequenceNumber - dest[index + 1].SequenceNumber) == 1) index++;

              if (index != dest.Count - 1) dest.Insert(index, x);
              else dest.Add(x);
              continue;
         }
         dest.Insert(index, x);
     }

     return dest;
} 

Interface and Class:

public interface ISequence
{
    int SequenceNumber { get; set; }
}
class Item : ISequence
{
    public int SequenceNumber { get; set; }

    public Item(int number)
    {
        SequenceNumber = number;
    }
}

Here is the usage (list1 and list2 are List<Item>):

var result = list1.ConcatItems(list2);

The method is working exactly what you want but you should implement it according to your situation and that part is up to you...

Here is a demonstration on LINQPad:

List1:

enter image description here

List2:

enter image description here

Output:

enter image description here

Last note: This method assumes your items are ordered.If they are not, first sort your items then call the method:

Comparison<Item> comp = (x, y) => x.SequenceNumber.CompareTo(y.SequenceNumber);
list1.Sort(comp);
list2.Sort(comp);
var result = list1.ConcatItems(list2);

OTHER TIPS

You can use the AddRange method from a list to combine another list of the same type. Wouldn't that accomplish what you are trying to do?

Please try this

var list = list1.Concat(list2);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top