Linq查找重复列表的最快方法

本文关键字:方法 列表 查找 Linq | 更新日期: 2023-09-27 18:13:19

给定的数据结构为:

class TheClass
{
    int NodeID;
    double Cost;
    List<int> NodeIDs;
}

和一个有数据的列表:

27 -- 10.0 -- 1, 5, 27
27 -- 10.0 -- 1, 5, 27
27 -- 10.0 -- 1, 5, 27
27 -- 15.5 -- 1, 4, 13, 14, 27
27 -- 10.0 -- 1, 4, 25, 26, 27
27 -- 15.5 -- 1, 4, 13, 14, 27
35 -- 10.0 -- 1, 4, 13, 14, 35

我想把它简化为唯一的NodeID列表

27 -- 10.0 -- 1, 5, 27
27 -- 15.5 -- 1, 4, 13, 14, 27
27 -- 10.0 -- 1, 4, 25, 26, 27
35 -- 10.0 -- 1, 4, 13, 14, 35

然后我将对"成本"列求和(节点27的总成本:10.0+15.5+10.0=35.5(——这部分是直接的。

删除重复行/查找唯一性的最快方法是什么?

生产数据集将具有100到200个ID的NodeID列表,列表中约有1500个,其中约500个是唯一的。

我100%专注于速度——如果添加一些其他数据会有所帮助,我很乐意(我曾尝试将列表哈希为SHA值,但结果比我目前的搜索速度慢(。

Linq查找重复列表的最快方法

.GroupBy(x=> string.Join(",", x.NodeIDs)).Select(x=>x.First())

对于大数据来说,这应该比Distinct更快。

如果您想根据相等的列表删除重复的对象,可以为列表创建一个自定义的IEqualityComparer<T>,并将其用于Enumerable.GroupBy。然后,您只需要为每个组创建新的类实例,并将Cost相加。

以下是一个可能的实现(来自(:

public class ListEqualityComparer<T> : IEqualityComparer<List<T>>
{
    public bool Equals(List<T> lhs, List<T> rhs)
    {
        return lhs.SequenceEqual(rhs);
    }
    public int GetHashCode(List<T> list)
    {
        unchecked
        {
            int hash = 23;
            foreach (T item in list)
            {
                hash = (hash * 31) + (item == null ? 0 : item.GetHashCode());
            }
            return hash;
        }
    }
}

这里有一个查询,它为每个组选择一个(唯一的(实例:

var nodes = new List<TheClass>(); // fill ....
var uniqueAndSummedNodes = nodes
    .GroupBy(n => n.NodeIDs, new ListEqualityComparer<int>())
    .Select(grp => new TheClass
    {
        NodeID = grp.First().NodeID,  // just use the first, change accordingly
        Cost = grp.Sum(n => n.Cost),
        NodeIDs = grp.Key
    });
nodes = uniqueAndSummedNodes.ToList();

此实现使用SequenceEqual,它考虑了列表中每个数字的出现顺序和次数。

编辑:我刚刚看到您不想汇总组的Costs,而是要汇总所有组的Cost,很简单:

double totalCost = nodes.Sum(n => n.Cost);

如果你不想总结小组本身,请更换

...
Cost = grp.Sum(n => n.Cost),

带有

...
Cost = grp.First().Cost, // presumes that all are the same