2011-07-25 128 views
3

我有两个不同的自定义类型的两个列表。这两种类型共享2个共同属性。C#LINQ比较列表值

例如:

List<foo>; 
List<bar>; 

他们都有属性,例如,一个名为名字和年龄。

我想返回一个包含所有条形对象的新列表,其中条形的名称和年龄属性存在于任何foo对象中。 什么是最好的方法来做到这一点?

感谢

回答

11

假设共享属性实现平等等正常,你可能想要做这样的事情:

// In an extensions class somewhere. This should really be in the standard lib. 
// We need it for the sake of type inference. 
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> items) 
{ 
    return new HashSet<T>(items); 
} 

var shared = foos.Select(foo => new { foo.SharedProperty1, foo.SharedProperty2 }) 
       .ToHashSet(); 

var query = bars.Where(bar => shared.Contains(new { bar.SharedProperty1, 
                bar.SharedProperty2 })); 

其他选项使用连接肯定会起作用 - 但我发现这更清楚地表达这样的想法,即您只想查看每个bar条目,即使有几个foo项目与该属性。

+1

如果有很多foos并且希望它运行得很快,'HashSet'就是正确的工具。 – Zebi

+0

谢谢乔恩。他们目前不实行平等。这是否意味着覆盖Equals和GetHashCode? –

+0

@达伦:是的。当然,默认的实现可能已经足够好了 - 这取决于你是否想要任何自定义的平等。 –

3

听起来像是你需要一个连接:

var fooList = new List<foo>(); 
var barList = new List<bar>(); 

// fill the lists 

var results = from f in fooList 
       join b in barList on 
        new { f.commonPropery1, f.commonProperty2 } 
        equals 
        new { b.commonProperty1, commonProperty2 = b.someOtherProp } 
       select new { f, b }; 
1

Any应该工作,如果是无关紧要多少Foo的比赛:

var selectedBars = bars.Where(bar => 
           foos.Any(foo => foo.Property1 == bar.Property1 
              && foo.Property2 == bar.Property2)); 

如果所有的Foo应该匹配使用All

var selectedBars = bars.Where(bar => 
           foos.All(foo => foo.Property1 == bar.Property1 
              && foo.Property2 == bar.Property2)); 

如果FOOS名单是大量使用的一个HashSet中指出, John Skeets回答。