【问题标题】:c# where in with list and linq时间:2019-05-10 标签:c#where in with list and linq
【发布时间】:2013-01-18 07:40:57
【问题描述】:

我有两个列表,一个是object A 的列表,另一个是objects B 的列表,如下所示:

ObjectA
{
    Int64 idObjectA;
    String name;
    ....
}

ObjectB
{
    Int64 idObjectB;
    Int64 idObjectA;
    String name;
    ....
}

我有两个列表,一个是Object A,另一个是Object B。我想创建一个只有objects B 的新list C,其中IDObjectAID 中的任何list A

在 SQL 中,它会是这样的一行:

select * from B where IDObjectA IN(1,2,3,4...);

在我的例子中,IN clause 的值列表是ObjectA 的列表,它具有idObjectA 属性。

【问题讨论】:

    标签: c# linq list where-in


    【解决方案1】:

    您可以使用Join linq 方法通过listBlistAidObjectA 来实现此目的,然后选择itemB

    var result = (from itemB in listB
                  join itemA in listA on itemB.idObjectA equals itemA.idObjectA
                  select itemB).ToList();
    

    此方法具有线性复杂度 (O(n))。使用 Where(... => ....Contains()) 或 double foreach 具有二次复杂度 (O(n^2))。

    【讨论】:

    • 很好的答案,但是在 99% 的情况下,ToList 是多余的。 (我假设问题中的术语List 用于指代任何序列IEnumerable<T>,而不是List<T>。)
    • Gideon 的解决方案复杂度O(n^2),效率低于我的。
    【解决方案2】:

    加入和不包含相同:

    var listC = listB.Join(listA, b => b.ObjectAId, a => a.Id, (b, a) => b).ToList();
    

    【讨论】:

    • 此解决方案具有线性或二次复杂度?唯一的区别是语法?谢谢。
    • @Daimroc 这与我的解决方案完全相同(在 O(n) 中)。 Raubi 使用 LINQ 扩展方法语法,我使用查询语法。
    【解决方案3】:

    这与连接方式略有不同。

    List<ObjectA> listA = ..
    List<ObjectB> listB = ..
    int[] listAIds = listA.Select(a => a.idObjectA).ToList();
                   //^^ this projects the list of objects into a list of ints
    
    //It reads like this...
    
    //get items in listB WHERE..
    listB.Where(b => listAIds.Contains(b.idObjectA)).ToList();
    //b.idObjectA is in listA, OR where listA contains b.idObjectA
    

    【讨论】:

    • 如果没有经过编译器优化,这是一个非常繁重的操作,因为对于 listB 中的每个项目,运行时都会使用 listA 的所有 id 构造一个新列表,并另外执行线性搜索。
    • 您可以使用以下命令简化表达式:listA.Any(a => a.idObjectA = b.idObjectA)(不为 b 中的每个元素实例化一个列表)。但是这个操作仍然是O(n^2)
    • @Jasd 很好!我修好了它。我只是想展示一种不同的方法,以便 OP 可以看到他的选项并理解 linq。 (我认识很多人不知道如何利用选定的预测)
    • 是的,有时很难理解 linq。有例子很好,比较复杂性是很好的。谢谢。
    【解决方案4】:

    不是 linq,而是做你想做的事:

    List<ObjectB> C = new List<ObjectB>();
    foreach (n in B)
    {
        foreach (c in A)
        {
            if (n.idObjectA == c.idObjectA)
            {
                C.Add(n)
                break;
            }
        }
    }
    

    或者,如果您想要更高的性能,请使用 for,比使用 Cédric Bignon 的解决方案更高。

    【讨论】:

    • 这个操作的复杂度是二次的。 Linq 提供了强大的方法使其成为线性(或接近线性)。
    • @CédricBignon 不,我写道,你的性能比我的高。到目前为止。我不知道你从哪里得到的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多