public class thing
{
public int Id{get;set;}
public decimal shouldMatch1 {get;set;}
public int otherMatch2{get;set;}
public string doesntMatter{get;set;}
public int someotherdoesntMatter{get;set;}
}
List<thing> firstList = new List<thing>();
List<thing> secondList = new List<thing>();
firstList.Add( new thing{ Id=1,shouldMatch1 = 1.11M, otherMatch2=1000,doesntMatter="Some fancy string", someotherdoesntMatter=75868});
firstList.Add( new thing{ Id=2,shouldMatch1 = 2.22M, otherMatch2=2000,doesntMatter="Some fancy string", someotherdoesntMatter=65345});
firstList.Add( new thing{ Id=3,shouldMatch1 = 3.33M, otherMatch2=3000,doesntMatter="Some fancy string", someotherdoesntMatter=75998});
firstList.Add( new thing{ Id=4,shouldMatch1 = 4.44M, otherMatch2=4000,doesntMatter="Some fancy string", someotherdoesntMatter=12345});
secondList.Add( new thing{ Id=100,shouldMatch1 = 1.11M, otherMatch2=1000,doesntMatter="Some fancy string", someotherdoesntMatter=75868});
secondList.Add( new thing{ Id=200,shouldMatch1 = 2.22M, otherMatch2=200,doesntMatter="Some fancy string", someotherdoesntMatter=65345});
secondList.Add( new thing{ Id=300,shouldMatch1 = 3.33M, otherMatch2=300,doesntMatter="Some fancy string", someotherdoesntMatter=75998});
secondList.Add( new thing{ Id=400,shouldMatch1 = 4.44M, otherMatch2=4000,doesntMatter="Some fancy string", someotherdoesntMatter=12345});
//Select new firstList.Id,secondList.Id where firstList.shouldMatch1 ==secondList.shouldMatch1 && firstList.otherMatch2==secondList.otherMatch2
//SHould return
//1,100
//4,400
有没有办法让列表相交,还是我必须迭代它们?
伪代码
firstList.Intersect(secondList).Where(firstList.shouldMatch1 == secondList.shouldMatch1 && firstList.otherMatch2 == secondList.otherMatch2)
Select new {Id1=firstList.Id,Id2=secondList.Id};
此致
_Eric
答案 0 :(得分:4)
您可以使用除交叉和实现IEqualityComparer之外的方法,如下所示:
var query = from f in firstList
from s in secondList
where f.shouldMatch1 == s.shouldMatch1 &&
f.otherMatch2 == s.otherMatch2
select new { FirstId = f.Id, SecondId = s.Id };
foreach (var item in query)
Console.WriteLine("{0}, {1}", item.FirstId, item.SecondId);
这基本上是查询格式的Enumerable.SelectMany method。联接可能比这种方法更快。
答案 1 :(得分:2)
考虑使用多条件联接来加入记录。交叉会导致您在左侧或右侧丢失ID。
以下是此特定方案的工作多列连接的示例。此查询的吸引力在于它不需要相等比较器,并且它允许您在连接其他指定列时检索ID列。
var query = from first in firstList
join second in secondList on
new { first.shouldMatch1, first.otherMatch2 }
equals
new { second.shouldMatch1, second.otherMatch2 }
select new
{
FirstId = first.Id,
SecondId = second.Id
};
答案 2 :(得分:1)
您需要使thing
类型覆盖Equals
和GetHashCode
来表明其等同语义:
public sealed class Thing : IEquatable<Thing>
{
public int Id{get;set;}
public decimal ShouldMatch1 {get;set;}
public int OtherMatch2{get;set;}
public string DoesntMatter{get;set;}
public int SomeOtherDoesntMatter{get;set;}
public override int GetHashCode()
{
int hash = 17;
hash = hash * 31 + ShouldMatch1.GetHashCode() ;
hash = hash * 31 + OtherMatch2.GetHashCode() ;
return hash;
}
public override bool Equals(object other) {
return Equals(other as Thing);
}
public bool Equals(Thing other) {
if (other == null) {
return false;
}
return ShouldMatch1 == other.ShouldMatch1 &&
OtherMatch2 == other.OtherMatch2;
}
}
请注意,密封类会使等式测试更简单。另请注意,如果您将其中一个作为键放入字典中,然后更改Id,ShouldMatch1或OtherMatch2,您将无法再次找到它...
现在,如果您使用真正的匿名类型,则无法执行此操作...并且实现IEqualityComparer<T>
传递给{{1}是很棘手的当它是匿名的时候。您可以编写一个Intersect
方法,有点像MoreLINQ的DisinctBy
方法......如果您真的使用匿名类型,这可能是最干净的方法。
你会这样使用它:
IntersectBy
然后你得到一个var query = first.Intersect(second);
,你可以得到正确的位。
另一种选择是使用联接:
IEnumerable<Thing>
(编辑:我刚注意到其他人也加入了......好啊。)
然而另一个选项,如果你只对匹配的位感兴趣,那就是投射序列:
var query = from left in first
join right in second
on new { left.ShouldMatch1, left.OtherMatch2 } equals
new { right.ShouldMatch1, right.OtherMatch2 }
select new { left, right };
答案 3 :(得分:0)
您需要一个相等比较器:
public class thingEqualityComparer : IEqualityComparer<thing>
{
#region IEqualityComparer<thing> Members
public bool Equals(thing x, thing y) {
return (x.shouldMatch1 == y.shouldMatch1 && x.otherMatch2 == y.otherMatch2)
public int GetHashCode(thing obj) {
// if this does not suffice provide a better implementation.
return obj.GetHashCode();
}
#endregion
}
然后您可以将集合与:
相交firstList.Intersect(secondList, new thingEqualityComparer());
或者,您可以覆盖Equal
函数(请参阅John的解决方案)。
另请注意,thing
不是匿名课程 - 例如new { prop = 1 }
。