筛选.Net中包含(几乎)重复项的列表的最有效方法

筛选.Net中包含(几乎)重复项的列表的最有效方法,.net,algorithm,linq,sorting,grouping,.net,Algorithm,Linq,Sorting,Grouping,我有一个.Net后端,它允许我通过相应的客户端API,通过它们的.Id和.Revision属性来查询项目,更好的是,通过提供这些组合的列表来批量查询项目 但是,每个.Id在每个查询中只能出现一次,但输入中确实包含多次具有相同Id的某些条目,但具有不同的.Revision值,例如: .Id | .Revision 1 | 1 1 | 2 2 | 1 (unique .Id) 3 | 3 3 | 5 4 | 2 (unique .Id) 5 | 1 (unique .Id

我有一个.Net后端,它允许我通过相应的客户端API,通过它们的.Id和.Revision属性来查询项目,更好的是,通过提供这些组合的列表来批量查询项目

但是,每个.Id在每个查询中只能出现一次,但输入中确实包含多次具有相同Id的某些条目,但具有不同的.Revision值,例如:

.Id | .Revision
1   | 1
1   | 2
2   | 1 (unique .Id)
3   | 3
3   | 5
4   | 2 (unique .Id)
5   | 1 (unique .Id)
。。因此,Id为1和3的条目基本上会导致问题,我想知道检索所有组合的最有效方式(即查询量最少)是什么

最糟糕的情况是,在运行时一个接一个地检索所有组合,而忽略了潜在的批量/批处理机制,但即使这在逻辑上会返回正确的项集,它显然很慢


如何获得最大的unqiue.Id/.Revision组合集,并以最少的批数将剩余的多个-.Id组合组合在一起。。高效?

通过循环中的几个LINQ表达式,您应该能够相对轻松地实现这一点

例如,假设您有一个
Item
类,如下所示:

public class Item
{
    public int Id { get; set; }
    public int Rev { get; set; }
}
以及这些项目的列表:
列表项。在一个批中,
Id
不能出现多次

使用
Distinct
,您可以非常轻松地获得第一个查询:

var queryItems = Items.Distinct(new ItemIdComparer()).ToList();
还有你的比较器:

public class ItemIdComparer: IEqualityComparer<Item>
{
    public int Equals(Item x, Item y)
    {
        return x.Id == y.Id;
    }

    public int GetHashCode(Item x)
    {
        return x.Id;
    }
}
如果将其放入循环中,则可以重复执行该操作,直到
剩余
列表为空:

var workingItems = Items.ToList();
while (workingItems.Count > 0)
{
    var queryItems = workingItems.Distinct(new ItemIdComparer()).ToList();
    var leftover = workingItems.Except(queryItems, new ItemComparer()).ToList();
    DoQuery(queryItems);
    workingItems = leftover;
}

使用此算法,只需两次查询即可获得所有项目的信息。第一个将得到项目1.1、2.1、3.3、4.2和5.1。第二个查询将得到1.2和3.5。

给定此格式的条目列表:

public class Entry
{
    public int Id { get; set; }
    public int Version { get; set; }
}
按Id分组,然后投影一个新的元素列表,每个条目的Id、版本和等级标记为批号,怎么样?排名将在具有相同Id的所有条目中。然后,您可以将具有相同批号的所有条目分组,并一次提交一批

以下是我的表达:

var entries = GenerateEntries();

    var result = entries
        .GroupBy(e => e.Id)
        //project new entries with a batch number 
        .SelectMany(g => g.Select((e, i) => new { Id = e.Id, Version = e.Version, Batch = i }))
        .GroupBy(e => e.Batch);

linq映射到的底层技术是什么?@CapTec没有用于查询后端的linq提供程序,查询之前的对象是纯内存对象,属于自定义类型,基本上客户端API只接受int[]作为.Id和.Revision值。因此,以最少的批处理量在内存中本地进行批处理。您可以从唯一ID生成一个树,并且在每个分支下,每个修订都有节点。这样,您就可以在每个节点需要时查询api。(以说话的方式思考你的问题)。不过我可能误解了你的问题。我对XML也做了类似的工作,以便在运行内存中保持较低的内存占用,相同的主体可以用于查询API。虽然这可以工作,但需要4个单独的查询来获取示例中项目的信息。这可以分两步完成。我不明白这将如何导致对数据库的更多查询。你能解释一下吗?在执行任何查询之前,所有这些逻辑都在他的内存列表中运行。我编写了一个快速应用程序来仔细检查这一点,它导致了两个批次。第一个有1.1、2.1、3.3、4.2和5.1。第二批为1.2和3.5。这和你的代码不一样吗?
GetHashCode
应该是
x.Id^x.Rev
,而不是
x.Id^y.Id
。@Porges:谢谢。固定的。
public class Entry
{
    public int Id { get; set; }
    public int Version { get; set; }
}
var entries = GenerateEntries();

    var result = entries
        .GroupBy(e => e.Id)
        //project new entries with a batch number 
        .SelectMany(g => g.Select((e, i) => new { Id = e.Id, Version = e.Version, Batch = i }))
        .GroupBy(e => e.Batch);