繁体   English   中英

在C#中查找表的最有效方法是什么?

[英]What is the most efficient way to do look-up table in C#

在C#中查找表的最有效方法是什么?

我有一张查询表。 有点像

0 "Thing 1"
1 "Thing 2"
2 "Reserved"
3 "Reserved"
4 "Reserved"
5 "Not a Thing"

因此,如果有人想要“Thing 1”或“Thing 2”,他们会传递0或1.但是他们也可以传递其他内容。 我有256种这类东西,其中200种是保留的。

那么最有效的想法是什么呢?

  • 字符串数组或字典变量,用于获取所有值。 然后取整数并返回该位置的值。

我对此解决方案的一个问题是所有“保留”值。 我不想创建那些冗余的“保留”值。 或者我可以对所有“保留”的所有地方都有一个if语句,但它们现在可能只有2-3,可能是2-3,40-55以及字节中的所有不同位置。 这个if语句会变得非常快速

  • 我想的另一个选择是switch语句。 而且我将获得所有50个已知值并且将通过默认值保留值。

我想知道这是否比创建一个字符串数组或字典更多的处理,只是返回适当的值。

  • 别的什么? 还有另一种方法可以考虑吗?

“通过使用其键来检索值非常快,接近于O(1),因为Dictionary(TKey,TValue)类被实现为哈希表。”

var things = new Dictionary<int, string>();
things[0]="Thing 1";
things[1]="Thing 2";
things[4711]="Carmen Sandiego";

在C#中查找整数值的绝对最快方法是使用数组。 如果您尝试一次进行数万次查找,这可能比使用字典更可取。 在大多数情况下,这是过度的; 您更有可能需要优化开发人员时间而不是处理器时间。

如果保留键不仅仅是查找表中没有的所有键(即,如果查找键可以返回找到的值,未找到状态或保留状态),则需要保存保留键在某处。 将它们保存为具有魔术值的字典条目(例如,保留值为null的任何字典条目的键)是正常的,除非您编写的代码迭代字典的条目而不过滤它们。

解决该问题的一种方法是使用单独的HashSet<int>来存储保留的键,并且可以将整个事物烘焙到类中,例如:

public class LookupTable
{
   public readonly Dictionary<int, string> Table { get; }
   public readonly HashSet<int> ReservedKeys { get; }

   public LookupTable()
   {
      Table = new Dictionary<int, string>();
      ReservedKeys = new HashSet<int>();
   }

   public string Lookup(int key)
   {
      return (ReservedKeys.Contains(key))
         ? null
         : Table[key];
   }
}

你会注意到这仍然存在魔术值问题 - 如果密钥是保留的, Lookup返回null,如果它不在表中,则抛出异常 - 但至少现在你可以迭代Table.Values而不过滤魔术值。

如果你有很多保留(当前未使用)的值或者整数值的范围可以变得很大,那么我会使用通用字典(Dictionary):

var myDictionary = new Dictionary<int, string>();
myDictionary.Add(0, "Value 1");
myDictionary.Add(200, "Another value");
// and so on

否则,如果你有一个固定数量的值,并且只有少数当前未被使用,那么我将使用一个字符串数组(字符串[200])并将保留的条目设置/保留为空。

var myArray = new string[200];
myArray[0] = "Value 1";
myArray[2] = "Another value";
//myArray[1] is null

查看HybridDictionary。 它会根据大小自动调整其底层存储机制,以获得最大效率。

http://msdn.microsoft.com/en-us/library/system.collections.specialized.hybriddictionary.aspx

内置的Dictionary对象(最好是通用字典)对此是理想的,并且专门设计用于快速/有效地检索与键相关的值。

从链接的MSDN文章:

通过使用其键来检索值非常快,接近于O(1),因为Dictionary <(Of <(TKey,TValue>)>)类被实现为哈希表。

就你的“保留”键而言,如果我们只讨论几百个键/值,我根本不会担心。 只有当你达到数十,甚至数十万个“保留”键/值时,你才能实现更有效的效果。

在这些情况下,可能最有效的存储容器可能是稀疏矩阵的实现。

我不太确定我是否理解你的问题。 你有一组字符串。 每个字符串都与索引相关联。 除非保留索引,否则使用者请求会提供索引并返回相应的字符串。 对?

你不能简单地在数组中将保留项设置为null。

如果没有,使用不包含保留项的字典似乎是一个合理的解决方案。

无论如何,如果你澄清你的问题,你可能会得到更好的答案。

将所有值加载到

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

并使用它来检索:

string GetDescription(int val)
{
     if(0 <= val && val < 256)
        if(!dic.Contains(val))
           return "Reserved";
        return dic[val];
    throw new ApplicationException("Value must be between 0 and 255");
}

我会使用Dictionary来进行查找。 到目前为止,这是最有效的查找方式。 使用字符串将在O(n)区域中的某处运行以查找对象。

如果需要,可以让第二个字典对所有人进行反向查找

您的问题似乎暗示查询键是一个整数。 由于您最多有256个项目,因此查询键的范围为0..255,对吗? 如果是这样,只需要一个256字符串的字符串数组,并使用该键作为数组的索引。

如果您的查询键是字符串值,那么它更像是一个真正的查找表。 使用Dictionary对象很简单,但是如果你的原始速度只有50个左右的实际答案,那么自己动手的方法,比如二元搜索或trie,可能会更快。 如果您使用二进制搜索,由于项目数量太少,您可以将其展开。

项目列表多久更改一次? 如果它只是很少变化,你可以通过生成代码进行搜索来获得更好的速度,然后你可以编译并执行每个查询。

另一方面,我假设你已经证明这个查找是你的瓶颈,无论是通过分析还是采用stackshots 如果在此查询中花费的时间少于10%,那么它不是您的瓶颈,因此您可以做最容易编码的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM