我如何在.NET中使用哈希表/哈希集?

11

我有一个大约9000个产品的列表,其中有一些可能会有重复的。

我想用这些产品的序列号作为键来创建一个哈希表,以便轻松查找重复项。

在C#/.NET中如何使用哈希表?使用HashSet是否更合适?

最终,我想得到这样一个列表:

Key-Serial: 11110 - 包含:Product1
Key-Serial: 11111 - 包含:Product3、Product6、Product7
Key-Serial: 11112 - 包含:Product4
Key-Serial: 11113 - 包含:Product8、Product9

因此,我有一个所有产品的列表,并且它们被分组为具有重复序列号的产品。什么是“正确”的做法?

6个回答

14

我认为Dictionary类是处理这种情况的推荐类。

在你的情况下,它可能是这样的。

Dictionary<string, List<Product>>

(使用串行字符串作为键)


那是一个临时应急的解决方案,你怎么能从列表中选择正确的产品呢?没有唯一键是无法替代的。 - Aviad P.
8
为什么这是个不完美的解决方案?这个问题是关于按序列对产品进行分组的。这是一个简单、直接并且易于理解的回答,符合要求,不是吗? - peter p

8
一个哈希表是一种字典,而哈希集合则是一种集合。字典和集合都无法直接解决您的问题 - 您需要一个数据结构来保存一个键对应的多个对象。
这样的数据库通常被称为multimaps。您可以通过使用哈希表来创建一个multimap,其中键的类型为整数,值的类型为某些类型的集合(例如哈希集合)。
或者,您可以查看现有的multimap解决方案,例如:.NET中的multimap
关于使用哈希表的信息,可以在MSDN上查看:http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx,还有很多其他教程 - 搜寻“HashTable”或“Dictionary”。

6
一个通用的字典可能是最适合这个的,我想。代码可能看起来像这样:

var keyedProducts = new Dictionary<int,List<string>>();

foreach (var keyProductPair in keyProductPairs)
{
  if (keyedProducts.Contains(keyProductPair.Key))
    keyedProducts[keyProductPair.Key].Add(keyProductPair.Product);
  else
    keyedProducts.Add(keyProductPair.Key, new List<string>(new[]{keyProductPair.Product}));
}

3

现在在.NET中可用的一个很好的选项是Lookup类。根据MSDN文档:

Lookup(Of TKey, TElement)类似于Dictionary(Of TKey, TValue)。不同之处在于,Dictionary(Of TKey, TValue)将键映射到单个值,而Lookup(Of TKey, TElement)将键映射到值的集合。

Lookup和Dictionary(Of List)之间存在一些差异。即,Lookup是不可变的(创建后无法添加或删除元素或键)。根据您计划如何使用数据,与GroupBy()相比,Lookup可能更有优势


1

首先,您需要定义您的“主键”,即一组对于每个对象都是唯一的字段。我猜Key-Serial将是该集合的一部分,但必须还有其他字段。一旦定义了该“主键”,您可以定义一个表示Key Value的结构体,并将其用作包含产品的字典的键。

例如:

struct ProductPrimaryKey
{
    public string KeySerial;
    public string OtherDiscriminator;

    public ProductPrimaryKey(string keySerial, string otherDiscriminator)
    {
        KeySerial = keySerial;
        OtherDiscriminator = otherDiscriminator;
    }
}

class Product
{
    public string KeySerial { get; set; }
    public string OtherDiscriminator { get; set; }
    public int MoreData { get; set; }
}

class DataLayer
{
    public Dictionary<ProductPrimaryKey, Product> DataSet 
        = new Dictionary<ProductPrimaryKey, Product>();

    public Product GetProduct(string keySerial, string otherDiscriminator)
    {
        return DataSet[new ProductPrimaryKey(keySerial, otherDiscriminator)];
    }
}

0

如果您只想要一个重复项列表,可以:

  • 创建一个Dictionary<T>来存储表格条目(我们称之为IEnumerable<T>,它会忽略重复的键)

  • 创建一个相同的IEnumerable<T>Hashset<T>(只要整行不同,就会保留重复的键)

  • 然后遍历dictionary.Values,对于每个值调用hashset.Remove(value)

hashset中剩下的就是重复项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接