2013-02-16 78 views
1

我在C#2名列表:交叉這兩個列表的最好方法是什麼?

public class AvailableSlot 
{ 
    public DateTime DateTime; 
    public string Name 
} 

List<AvailableSlot> list1 = GetList(); 
List<AvailableSlot> list2 = GetAnotherList(); 

我想打電話給相交這些列表中找出有兩個列表中同一日期的項目。我知道我可以使用.Intersect來獲取這個信息,但我有一個稍微複雜的要求。我想返回一個相交的列表,但我想要這個列表包含一個列表中包含所有名稱的對象。所以是這樣的:

List<AvailableSlot2> intersectedList . .. 

其中AvailableSlot2是下面這樣:

public class AvailableSlot2 
{ 
    public DateTime DateTime; 
    public string[] Names; 
} 

有沒有嘗試兩個列表之間相交後做這種轉變的能力?

+1

是'DateTime'在列表中唯一嗎? – GolfWolf 2013-02-16 18:58:48

回答

2

我只想工會這兩個列表,按日期時間,然後從組拉出名稱:

var list1 = new List<AvailableSlot> 
{ 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 1), Name = "Alpha" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 2), Name = "Bravo" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 3), Name = "Charlie" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 1), Name = "Delta" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 2), Name = "Echo" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 3), Name = "Foxtrot" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 4), Name = "Golf" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 5), Name = "Hotel" } 
}; 

var list2 = new List<AvailableSlot> 
{ 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 1), Name = "Apple" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 2), Name = "Bannana" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 1), Name = "Dog" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 2), Name = "Egg" }, 
    new AvailableSlot { DateTime = new DateTime(2013, 2, 5), Name = "Hi" } 
}; 

var list3 = list1.Where (l => list2.Where (li => l.DateTime == li.DateTime).Any()) 
    .Union(list2.Where (l => list1.Where (li => l.DateTime == li.DateTime).Any())); 

var groupedItems = from slot in list3 
    group slot by slot.DateTime into grp 
    select new AvailableSlot2 { 
     DateTime = grp.Key, 
     Names = grp.Select (g => g.Name).ToArray() 
    }; 

foreach(var g in groupedItems) 
{ 
    Console.WriteLine(g.DateTime); 
    foreach(var name in g.Names) 
     Console.WriteLine(name); 
    Console.WriteLine("---------------------"); 
} 

輸出:

2/1/2013 12:00:00 AM 
Alpha 
Delta 
Apple 
Dog 
--------------------- 
2/2/2013 12:00:00 AM 
Bravo 
Echo 
Bannana 
Egg 
--------------------- 
2/5/2013 12:00:00 AM 
Hotel 
Hi 
--------------------- 
+0

由於某種原因,我仍然在我的最終列表中得到的結果只存在於其中一個列表中(不是兩個)。 .still調試 – leora 2013-02-16 19:29:21

+0

@leora,確定,爲真實交集添加了一些代碼,以便DateTime必須位於兩個列表中。請參閱上面的註釋代碼。 – 2013-02-16 19:31:07

0

您可以使用LINQ到對象Join()排隊用相同的日期時間屬性項,然後收集所有的名字到一個數組

var joinedItems = from slot1 in list1 
        join slot2 in list2 
        on slot1.DateTime equals slot2.DateTime into g 
        where g.Any() 
        select new AvailableSlot2 
        { 
         DateTime = slot1.DateTime, 
         Names = Enumerable.Range(slot1.Name,1).Union(g.Select(s => s.Name)).ToArray() 
        } 
+0

Enumerable.Range()似乎想要2個int參數,所以這不會編譯 – leora 2013-02-16 18:38:01

+0

爲什麼這是downvoted?這個想法完全有效。 – usr 2013-02-16 19:07:53

+0

@leora參見編輯 – cordialgerm 2013-02-17 04:48:06

0

您可以使用ToLookup

DateTime dt1 = new DateTime(2013, 2, 1); 
DateTime dt2 = new DateTime(2013, 3, 1); 
DateTime dt3 = new DateTime(2013, 4, 1); 

var list1 = new List<AvailableSlot> 
{ 
    new AvailableSlot{DateTime = dt1, Name = "n1",}, 
    new AvailableSlot{DateTime = dt2, Name = "n2",}, 
    new AvailableSlot{DateTime = dt1, Name = "n3",}, 
}; 

var list2 = new List<AvailableSlot> 
{ 
    new AvailableSlot{DateTime = dt1, Name = "n1",}, 
    new AvailableSlot{DateTime = dt2, Name = "n2",}, 
    new AvailableSlot{DateTime = dt3, Name = "n3",}, 
}; 

var intersected = list1.Select (l => l.DateTime). 
         Intersect(list2.Select (l => l.DateTime)); 

var lookup = list1.Union(list2).ToLookup (
           slot => slot.DateTime, slot => slot); 

lookup.Where (l => intersected.Contains(l.Key)).Select (
    slot => new 
    { 
     DateTime=slot.Key, 
     Names=slot.Select (s => s.Name) 
    }); 

在這種情況下給出結果:

DateTime   Names 

01/02/2013 00:00 n1 
        n3 
        n1 

01/03/2013 00:00 n2 
        n2 

你當然可以使用同樣的名稱= slot.Select(S => s.Name).Distinct ()來獲得一個明確的名稱列表。

相關問題