扩展方法,用于排除其id存在于另一个字段中的任何位置

时间:2017-11-14 06:37:07

标签: entity-framework linq linq-to-sql linq-to-xml

我需要从表格中获取数据。

这是表格的结构:

ID      PackageID     DESC  OriginalPackageID    Status
-------------------------------------------------------
1          00A        Test        Null             P

2          00B        xxxx        Null             P

3          00A        test1        1               W

我想使用扩展方法编写一个linq查询来获取Status = P的记录,但其中ID并不存在于任何记录中#39 ; OriginalPackageID

例如,ID = 1的记录有Status = P,但1是第三条记录OriginalPackageID。所以应该排除第一条记录。只返回第二条记录。

1 个答案:

答案 0 :(得分:0)

So you want all records from your table that have a Status equal to P and of which there is not any element in the table that has a value of OriginalPackageId equal to the ID of the record.

This description already says how to do this, although I'm not sure whether it is efficient:

IEnumerable<MyClass> table = ...
var result = table
    .Where(record => record.Status == P
       && !table.Any(item => item.OriginalPackageId == record.Id));

This is not efficient, befause for every record it will potentially have to check the complete table to check that its ID is not used as OriginalPackageId.

Luckily you don't care which record has a value of OriginalPackageId that equals your record's ID. Therefore you don't have to remember which record has this OriginalPackageId value.

You only need to remember that any record uses this OriginalPackageId value.

So let's first put the used OriginalPackageIds in a HashSet<int> object. This will cost you one pass on the elements of the table:

IEnumerable<int> allOriginalPackageIds = table
   .Select(record => record.OriginalPackageId);
HashSet<int> usedPackageIds = new HashSet<int>(allOriginalPackageIds);

The constructor of the HashSet will remove duplicates.

Now you can use HashSet.Contains中使用data-toggle =“tooltip”来查找是否在任何OriginalPackageID中使用了该ID。这是一个非常快速的功能。

您的扩展功能如下:

public static IEnumerable<MyClass> ExtractOriginalItems(
    this IEnumerable<MyClass> table)
{
    IEnumerable<int> allOriginalPackageIds = table
       .Select(record => record.OriginalPackageId);
    HashSet<int> usedPackageIds = new HashSet<int>(allOriginalPackageIds);

    foreach(var record in table)
    {
        // return elements with status P and not ID in hashset:
        if (record.Status == P && !usedPackageIds.Contains(record.Id))
        {
            yield return record;
        }
    }
}

创建HashSet是O(1) ForEach是O(1)