【问题标题】:Intersection of two sets (Lists) of data两组(列表)数据的交集
【发布时间】:2011-12-22 19:50:24
【问题描述】:

我有两组数据(复杂对象列表或 SQL 数据 - LINQ to Entities),我试图在其中找到两组数据的交集。特别是 Complex 属性的交集,“HashData”,如下所示:

左边的集合可能是大约 10000 行,而右边的集合总是大约 100 行的子集。我意识到,如果我在存储它时按“Hashdata”对左侧的集合进行排序,使用某种二进制搜索算法进行搜索会快得多,但是由于与问题无关的原因,我不能这样做。

较小的数据子集从不存储在 SQL 中(仅为说明目的而显示在下面的 SQL 表中)。它在运行时以List<ShowData> 的形式呈现。

目前我正在对数据进行一个可怜的循环并像这样进行匹配(其中recording 是 100 行列表,ShowData 是 10000 行列表):

List<ShowData> ShowData = (from showData in context.ShowDatas
                           where (showData.Show.Id == advert.Id)
                           orderby showData.HashData ascending
                           select showData).ToList();

foreach (ShowData recording in recordingPoints) {
    foreach (ShowData actual in ShowData) {
        if (recording.HashData == actual.HashData) {
        }
    }
}

所以基本上我想做的是:

返回一个 ShowData 对象列表(大集合),其中任何 HashData(来自小集合)在 ShowData 但在 LINQ to Entity 初始查询中找到 DB。

我接近了:

private IEnumerable<ShowData> xyz(List<ShowData> aObj, List<ShowData> bObj)
    {
        IEnumerable<string> bStrs = bObj.Select(b => b.HashData).Distinct();
        return aObj.Join(bStrs, a => a.HashData, b => b, (a, b) => a);
    }

【问题讨论】:

    标签: c# linq entity-framework entity intersection


    【解决方案1】:

    由于您使用的是 IEnumerable,因此您可以使用 Intersect Extension 方法而不是 Join。如果要返回大集合,则需要将大集合查询的结果与较小集合相交。您需要编写一个 IEquality 比较器,如下所示:http://msdn.microsoft.com/en-us/library/bb355408.aspx 来比较您的对象,然后调用 Intersect 扩展方法:

    return bStrs.Intersect(aObj, new MyEqualityComparer());
    

    【讨论】:

    • 嗨乔希,我试过这个:public bool Equals(ShowData x, ShowData y) { //Check whether the compared objects reference the same data. if (Object.ReferenceEquals(x, y)) return true; //Check whether any of the compared objects is null. if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; //Check whether the products' properties are equal. return x.HashData == y.HashData; }
    • 但我不确定这是如何编译的,因为我收到一个错误:iEnumerable 不包含 Intersect 的定义
    • @user1112324 - 你确定你已经为 'System.Linq' 和 'System.Collections.Generic' 包含了一个 'using' 语句吗? Intersect 无疑是 IEnumerable 的扩展方法。
    【解决方案2】:

    这样的事情可能会起作用(警告未经测试):

    private IEnumerable<ShowData> xyz(List<ShowData> aObj, List<ShowData> bObj)
    {
        return aObj.Where(sd1 => bObj.Select(sd2 => sd2.HashData).Contains(sd1.HashData));
    }
    

    【讨论】:

    • 嗨,我在上面尝试过,但是当我遍历这两组并计算匹配项(recording.HashData == actual.HashData)与我运行上面的方法时,我得到了不同的结果:IEnumerable 包含 = xyz(ShowData, recordingPoints); int 返回 = contains.Count();
    • 这可能是因为您的方法只获取唯一值(即,如果它已经在返回集中,则不要读取它)。即使它已经存在,我也需要读取它
    • Josh 的回答可能会更适合您的目的(尽管我不确定 Intersect 是否只提供 Distinct 结果)。
    猜你喜欢
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    • 1970-01-01
    • 2011-08-16
    相关资源
    最近更新 更多