在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语句会变得非常快速
我想知道这是否比创建字符串数组或字典要多得多,只返回适当的值。
答案 0 :(得分:13)
var things = new Dictionary<int, string>();
things[0]="Thing 1";
things[1]="Thing 2";
things[4711]="Carmen Sandiego";
答案 1 :(得分:4)
在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,如果不在表中,则抛出异常 - 但至少现在你可以迭代{ {1}}没有过滤魔术值。
答案 2 :(得分:3)
如果您有许多保留(当前未使用)值或者整数值的范围可能变得非常大,那么我会使用通用字典(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
答案 3 :(得分:2)
查看HybridDictionary。它会根据大小自动调整其底层存储机制,以获得最大效率。
http://msdn.microsoft.com/en-us/library/system.collections.specialized.hybriddictionary.aspx
答案 4 :(得分:0)
内置Dictionary对象(最好是通用字典)对此非常理想,专门用于快速/高效地检索与键相关的值。
来自链接的MSDN文章:
使用其键检索值是 非常快,接近O(1),因为 字典&lt;(Of&lt;(TKey,TValue&gt;)&gt;) class被实现为哈希表。
就你的“保留”键而言,如果我们只讨论几百个键/值,我根本不会担心。只有当你达到数十,甚至数十万个“保留”键/值时,你才能实现更有效的效果。
在这些情况下,最有效的存储容器可能是Sparse Matrix的实现。
答案 5 :(得分:0)
我不太确定我是否理解你的问题。你有一组字符串。每个字符串都与索引相关联。消费者请求提供索引并返回相应的字符串,除非索引是保留。正确?
你不能简单地在数组中将保留项设置为null。
如果没有,使用不包含保留项的字典似乎是一种合理的解决方案。
无论如何,如果你澄清问题,你可能会得到更好的答案。
答案 6 :(得分:0)
将所有值加载到
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");
}
答案 7 :(得分:0)
我会使用Dictionary来进行查找。到目前为止,这是最有效的查找方式。使用字符串将在O(n)区域的某处运行以找到对象。
如果需要的话,让第二个字典对你所有人进行反向查找可能是有用的
答案 8 :(得分:0)
您的问题似乎暗示查询键是一个整数。由于您最多有256个项目,因此查询键的范围为0..255,对吗?如果是这样,只需要一个256字符串的字符串数组,并使用该键作为数组的索引。
如果您的查询键是字符串值,那么它更像是一个真正的查找表。使用Dictionary对象很简单,但是如果你的原始速度只有50个左右的实际答案,那么自己动手的方法,比如二元搜索或trie,可能会更快。如果您使用二进制搜索,由于项目数量太少,您可以将其展开。
项目列表多久更改一次?如果它只是很少变化,你可以通过生成代码进行搜索来获得更好的速度,然后你可以编译并执行每个查询。
另一方面,我假设您已通过分析或taking stackshots证明此查找是您的瓶颈。如果在此查询中花费的时间少于10%,则不是您的瓶颈,因此您可以做最容易编码的事情。