【问题标题】:C# LINQ comparing list valuesC# LINQ 比较列表值
【发布时间】:2011-07-25 14:16:15
【问题描述】:

我有两个不同自定义类型的列表。这两种类型有 2 个共同的属性。

例如:

List<foo>;
List<bar>;

它们都有属性,例如名称和年龄。

我想返回一个包含所有 bar 对象的新列表,其中 bar 的 Name 和 Age 属性存在于任何 foo 对象中。 最好的方法是什么?

谢谢

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    假设共享属性正确实现相等等,您可能想要执行以下操作:

    // 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 并且您希望它快速运行。
    • 谢谢乔恩。他们目前没有实现平等。你的意思是覆盖 Equals 和 GetHashCode 吗?
    • @Darren:是的。当然,默认实现可能已经足够好了——这取决于您是否需要任何自定义的相等性。
    • @Jon,谢谢。数据集可能会变得非常大,所以我认为这可能是要走的路。
    【解决方案2】:

    听起来你需要加入:

    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 };
    

    【讨论】:

      【解决方案3】:

      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 回答中所指出的那样。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-06
        相关资源
        最近更新 更多