Ilan
Ilan

Reputation: 383

how to merge generic lists and their properties

i have 2 generic lists of the same type "Person" each list have List of "Order" property.
Person ID (identifier) can repeat in booth lists. but orders can not.
my desired output should be 1 list, when each person have one instance
and all the orders are merged.
my question is, what is the best way (performance) to do that ?
as explained in the next code:

class Program
{

    public class Order
    {
        public string OrderId { get; set; }
    }

    public class Person
    {
        public string Id { get; set; }
        public List<Order> orders { get; set; }
    }

    static void Main(string[] args)
    {

        // build list 1
        Person p1 = new Person() { Id = "John", orders = new List<Order>() };
        p1.orders.Add(new Order() { OrderId = "John order 1" });

        Person p2 = new Person() { Id = "Paul", orders = new List<Order>() };
        p2.orders.Add(new Order() { OrderId = "Paul order 1" });

        List<Person> L1 = new List<Person>();
        L1.Add(p1);
        L1.Add(p2);


        // build list 2
        Person p3 = new Person() { Id = "John", orders = new List<Order>() };
        p3.orders.Add(new Order() { OrderId = "John order 2" });

        List<Person> L2 = new List<Person>();
        L2.Add(p3);

        //output 
        List<Person> merged = new List<Person>();

        merged = L1.Union(L2, new PersonComparer()).ToList();


        foreach (var item in merged)
        {
            Console.WriteLine("Person ID: {0}", item.Id);
            foreach (var order in item.orders)
            {
                Console.WriteLine(" --  {0}", order.OrderId);
            }
            Console.WriteLine("-----------------");
        }

        Console.ReadKey();

    }

}

Output:

        /************************************************************
         * current output:
         *
         * Presone ID: John
         * ---  John order 1
         * -------------------------
         * Presone ID: Paul
         * ---  Paul order 1
         * ------------------------ 
         * Presone ID: John
         * ---  John order 2 
         * 
         * 
         * desired output:
         * 
         * Presone ID: John
         * ---  John order 1
         * ---  John order 2 
         * -------------------------
         * Presone ID: Paul
         * ---  Paul order 1
         * ------------------------  
         *    

Upvotes: 0

Views: 113

Answers (1)

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101731

Concat the lists, group by PersonId, then create a person for each group and concatenate the orders:

L1.Concat(L2)
 .GroupBy(x => x.Id)
 .Select(x => new Person 
              { 
                  Id = x.Key,
                  Orders = x.SelectMany(g => g.Orders).ToList()
              }).ToList();

You don't need Union here because you don't want to remove the duplicates.Even if your comparer works, it will remove the duplicate persons and you will lose the Orders.You need all Persons grouped by their Ids.Then once you get the groups you can easily get orders of all the persons in the group into a list.

Upvotes: 2

Related Questions