2013-02-16 77 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 ()来获得一个明确的名称列表。

相关问题