【发布时间】:2011-07-25 14:16:15
【问题描述】:
我有两个不同自定义类型的列表。这两种类型有 2 个共同的属性。
例如:
List<foo>;
List<bar>;
它们都有属性,例如名称和年龄。
我想返回一个包含所有 bar 对象的新列表,其中 bar 的 Name 和 Age 属性存在于任何 foo 对象中。 最好的方法是什么?
谢谢
【问题讨论】:
我有两个不同自定义类型的列表。这两种类型有 2 个共同的属性。
例如:
List<foo>;
List<bar>;
它们都有属性,例如名称和年龄。
我想返回一个包含所有 bar 对象的新列表,其中 bar 的 Name 和 Age 属性存在于任何 foo 对象中。 最好的方法是什么?
谢谢
【问题讨论】:
假设共享属性正确实现相等等,您可能想要执行以下操作:
// 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 具有该属性的项目。
【讨论】:
HashSet 是解决此问题的正确工具,如果有很多 foo 并且您希望它快速运行。
听起来你需要加入:
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 };
【讨论】:
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 回答中所指出的那样。
【讨论】: