我有两个IEnumerable
类型的实例,如下所示。
IEnumerable<Type1> type1 = ...;
IEnumerable<Type2> type2 = ...;
Type1
和Type2
都包含一个名为common
的成员,所以即使它们属于不同的类,我们仍然可以像这样关联它们。
type1[0].common == type2[4].common
我试图过滤掉type1
中common
中没有相应type2
值的元素,并根据每个元素中的一个值创建字典。现在,我通过以下双循环来做到这一点。
Dictionary<String, String> intersection = ...;
foreach (Type1 t1 in type1)
foreach(Type2 t2 in type2)
if (t1.common == t2.common)
intersection.Add(t1.Id, t2.Value);
现在,我已尝试使用LINQ但.Where
,.Select
和.ForEach
只是让我很头疼。有没有办法使用LINQ整齐地执行相同的操作?
答案 0 :(得分:15)
当两个序列有共同点并且您希望根据该共性过滤其产品时,高效查询是一个连接。假设 Type1 是 Customer 而 Type2 是 Order 。每个客户都有一个 CustomerID ,每个订单还有一个 CustomerID 。然后你可以这么说。
var query = from customer in customers
join order in orders
on customer.CustomerId equals order.CustomerId
select new { customer.Name, order.Product };
迭代将为您提供一系列配对,包括每个有订单的客户名称及其所有产品。因此,如果客户Suzy订购了煎饼和披萨,而顾客鲍勃订购了牛排,那么你就会得到这些牛排。
Suzy, pancake
Suzy, pizza
Bob, steak
如果您想要分组,以便每个客户都有他们的订单列表,那就是群组加入。
var query = from customer in customers
join order in orders
on customer.CustomerId equals order.CustomerId
into products
select new { customer.Name, products };
迭代,为您提供第一项为名称,第二项为产品序列的对。
Suzy, { pancake, pizza }
Bob, { steak }
答案 1 :(得分:1)
另一种选择是加入。我在下面做了一个快速的控制台应用程序,但不得不编写我自己的数据。希望我能正确理解你的问题。
public class Type1
{
public string ID { get; set; }
public Guid common { get; set; }
}
public class Type2
{
public string Value { get; set; }
public Guid common { get; set; }
}
class Program
{
static void Main(string[] args)
{
Guid CommonGuid = Guid.NewGuid();
IEnumerable<Type1> EnumType1 = new List<Type1>()
{
new Type1() {
ID = "first",
common = CommonGuid
},
new Type1() {
ID = "second",
common = CommonGuid
},
new Type1() {
ID = "third",
common = Guid.NewGuid()
}
} as IEnumerable<Type1>;
IEnumerable<Type2> EnumType2 = new List<Type2>()
{
new Type2() {
Value = "value1",
common = CommonGuid
},
new Type2() {
Value = "value2",
common = Guid.NewGuid()
},
new Type2() {
Value = "value3",
common = CommonGuid
}
} as IEnumerable<Type2>;
//--The part that matters
EnumType1 //--First IEnumerable
.Join( //--Command
EnumType2, //--Second IEnumerable
outer => outer.common, //--Key to join by from EnumType1
inner => inner.common, //--Key to join by from EnumType2
(inner, outer) => new { ID = inner.ID, Value = outer.Value }) //--What to do with matching "rows"
.ToList() //--Not necessary, just used so that I can use the foreach below
.ForEach(item =>
{
Console.WriteLine("{0}: {1}", item.ID, item.Value);
});
Console.ReadKey();
}
}
显示如下:
第一:值1
第一名:value3
第二名:value1
第二名:value3
答案 2 :(得分:0)
假设您仍希望将交叉点保持为Dictionary<string, string>
:
IEnumerable<Type1> list1;
IEnumerable<Type2> list2;
Dictionary<string, string> intersection =
(from item1 in list1
from item2 in list2
where item1.common = item2.common
select new { Key = item1.Id, Value = item2.Value })
.ToDictionary(x => x.Key, x => x.Value);
答案 3 :(得分:-1)
type1.where(i=>type2.where(j=>j.common == i.common).Count > 0);
这应该只列出那些匹配的列表。
答案 4 :(得分:-1)
我错过了什么,但是会这样做:
type1
.where(t1 => type2.Any(t2 => t1.common == t2.common)
.ToDictionary(t1 => t1.Id)
或者像Servy建议的那样
type1
.Join(type2, a => a.common, b => b.common, (a1,b1) => a1)
.ToDictionary(t1 => t1.Id)