LINQ Join 2 Lists

后端 未结 4 875
感情败类
感情败类 2020-11-29 07:36

Preface: I don\'t understand what this does:

o => o.ID, i => i.ID, (o, id) => o

So go easy on me. :-)


I have 2 lis

相关标签:
4条回答
  • 2020-11-29 07:42

    Here is what I came up with (based on this):

            List<Contact> list3 = (from item1 in list1
                join item2 in list2
                on item1.ContactID equals item2.ContactID into g
                from o in g.DefaultIfEmpty()
                select o == null ? item1 :o).ToList<Contact>();
    

    My favorite part is the big nosed smiley

    :o)

    Thanks for your help!

    0 讨论(0)
  • 2020-11-29 07:48

    It looks like you don't really need a full-join. You could instead do a semi-join, checking each contact in list 2 to see if it is contained in list 1:

    ContactCollection list3 = list2.Where(c => list1.Contains(c));

    I don't know how big your lists are, but note that this approach has O(nm) complexity unless list1 is sorted or supports fast lookups (as in a hashset), in which case it could be as efficient as O(nlog(m)) or rewritten as a merge-join and be O(n).

    0 讨论(0)
  • 2020-11-29 07:59

    Joins are not so difficult, but your problem could probably use some further explanation.

    To join two lists, you could do something like

    var joined = from Item1 in list1
                 join Item2 in list2
                 on Item1.Id equals Item2.Id // join on some property
                 select new { Item1, Item2 };
    

    this will give an IEnumerable<'a>, where 'a is an anonymous type holding an item from list1 and its related item from list2. You could then choose which objects' properties to use as needed.

    To get the result to a concrete list, all that is needed is a call to .ToList(). You can do that like

    var list3 = joined.ToList();
    // or
    var list3 = (from Item1 in list1
                 join Item2 in list2
                 on Item1.Id equals Item2.Id // join on some property
                 select new { Item1, Item2 }).ToList();
    

    To do a left join to select all elements from list1 even without a match in list2, you can do something like this

    var list3 = (from Item1 in list1
                 join Item2 in list2
                 on Item1.Id equals Item2.Id // join on some property
                 into grouping
                 from Item2 in grouping.DefaultIfEmpty()
                 select new { Item1, Item2 }).ToList();
    

    This will give you a list where Item1 equals the item from the first list and Item2 will either equal the matching item from the second list or the default, which will be null for a reference type.

    0 讨论(0)
  • 2020-11-29 08:08

    Here is a DotNetFiddle with a Linq Group Join

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    
    class Order 
    {
        public int Id;
        public string Name;
        public Order(int id, string name)
        {
            this.Id = id;
            this.Name = name;
        }   
    }
    class OrderItem
    {
        public int Id;
        public string Name;
        public int OrderId;
        public OrderItem(int id, string name, int orderId)
        {
            this.Id = id;
            this.Name = name;
            this.OrderId = orderId;
        }
    }
    List<Order> orders = new List<Order>() 
    {
        new Order(1, "one"), 
        new Order(2, "two") 
    };
    List<OrderItem> orderItems = new List<OrderItem>()
    {
        new OrderItem(1, "itemOne", 1),
        new OrderItem(2, "itemTwo", 1), 
        new OrderItem(3, "itemThree", 1), 
        new OrderItem(4, "itemFour", 2), 
        new OrderItem(5, "itemFive", 2)
    };
    var joined = 
        from o in orders
        join oi in orderItems
        on o.Id equals oi.OrderId into gj // gj means group join and is a collection OrderItem
        select new { o, gj };
    
    // this is just to write the results to the console
    string columns = "{0,-20} {1, -20}";
    Console.WriteLine(string.Format(columns, "Order", "Item Count"));
    foreach(var j in joined)
    {
        Console.WriteLine(columns, j.o.Name, j.gj.Count() );
    }
    
    0 讨论(0)
提交回复
热议问题