【问题标题】:linq - How to find if one collection's key columns are a subset of another collection?linq - 如何查找一个集合的键列是否是另一个集合的子集?
【发布时间】:2017-02-10 17:26:58
【问题描述】:

我在 C# 中使用 .NET 4.5,并且我有两个不同类的集合,我试图比较它们。它们有一些名称相似的列,但它们没有实现通用接口(出于编码标准的原因也不能实现)。

第一个类是这样的:

class Foo
{
    string Key1 {get; set;}
    string Key2 {get; set;}
    string NotKey {get; set;}
    string AlsoNotKey {get; set;}
}

第二个看起来像这样:

class Bar
{
    string Key1 {get; set;}
    string Key2 {get; set;}
}

我想要做的是将Foo 的集合传递给一个方法并返回true,当其中的每对不同的Key1Key2 在从以下位置检索到的Bar 集合中匹配时一个数据库(通过 EF),但我不知道该怎么做。

我的第一个想法看起来像这样......

//IEnumerable<Foo> foos
//DbSet<Bar> bars
foos.All(foo => foo.Key1 == bars.Key1 && foo.Key2 == bars.Key2)

...但它不起作用,因为bars 也是一个集合,我不能只在每一列周围使用Contains(),因为这样它就不会将两列作为一对进行比较。

在 SQL 中,我可以做类似的事情

SELECT COUNT(*)
FROM foos
JOIN bars
ON foos.key1 = bars.key1
AND foos.key2 = bars.key2

并将其与 foos 中的记录数进行比较,但如何将其转换为 LINQ?

编辑:找到了这个相关的问题。 How to use linq `Except` with multiple properties with different class?

可能会尝试这样的事情,除非有更好的方法。

foos.All(f => bars.Any(b => f.Key1 == b.Key1 && f.Key2 == b.Key2))

【问题讨论】:

标签: c# .net entity-framework linq


【解决方案1】:

试试这个:

var x = (from f in foos
         join b in bars on new { f.Key1, f.Key2 } equals new { b.Key1, b.Key2 }
         select f).Count();

我知道它是一个长格式,但在这种情况下它比短格式更具描述性。

显然,最大的假设是您的密钥不会重复。如果他们这样做,您将得到错误的项目计数

【讨论】:

    【解决方案2】:

    试试这个

    bool IsFooASubsetOfBar(List<Foo> foos, List<Bar> bars)
    {
        if (foos == null || bars == null)
            return false;
    
        return foos.All(foo => bars.Any(bar => bar.Key1 == foo.Key1 && bar.Key2 == foo.Key2));
    }
    

    用法:

    List<Bar> bars = new List<Bar>()
                {
                    new Bar() { Key1 = "1", Key2 = "1" },
                    new Bar() { Key1 = "2", Key2 = "2" },
                    new Bar() { Key1 = "3", Key2 = "3" }
                };
    
    List<Foo> foos = new List<Foo>()
                {
                    new Foo() { Key1 = "2", Key2 = "2" },
                    new Foo() { Key1 = "3", Key2 = "3" }
                };
    
    bool b = IsFooASubsetOfBar(foos);
    

    【讨论】:

      【解决方案3】:

      您可以使用join,但我不会使用count,因为这会迫使您考虑重复的键元组。我会改用left join

      public bool Matches(IEnumerable<Foo> foos, DbSet<Bar> bars)
      {
             return (from f in foos
                     join b in bars on new {f.Key1, f.Key2} equals new {b.Key1, b.Key2} into fjb
                     from match in fjb.DefaultIfEmpty()
                     select match != null
                     ).All(isMatch => isMatch);       
      }
      

      【讨论】:

        猜你喜欢
        • 2021-04-05
        • 2021-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多