我有一个大约500个字符串的列表“joe”“john”“jack”...“jan”
我只需要找到序数。
在我的例子中,列表永远不会改变。
可以将它们放在列表和IndexOf
中ll.Add("joe")
ll.Add("john")
...
ll.Add("jan")
ll.IndexOf("jib") is 315
或者你可以使用序数整数作为值将它们放在字典中,
dd.Add("joe", 1)
dd.Add("john", 2)
dd.Add("jack", 3)
...
dd.Add("jan", 571)
dd["jib"] is 315
FTR字符串长度为3到8个字符。 FTR这是一个统一的,因此Mono,环境。
1)纯粹为了表现,一种方法通常更受欢迎?
1b实际上,我发现了许多这种性质的分析:http://www.dotnetperls.com/dictionary-time(google进行了大量类似的分析)。这适用于我描述的情况还是我在这里?2)关于哪个在一般的开发工程意义上更好。 (完全抛开表现。)在我看来,两者都有明显的优点和缺点; 既不优雅。
3)遗憾的是没有“HashSetLikeThingWithOrdinality”类型的设施 - 如果我错过了明显的请告诉我们。实际上,这似乎是一个相当普遍的,基本的集合用例 - “获得一些字符串的序数” - 也许我完全错过了一些明显的东西。
答案 0 :(得分:5)
以下是使用Dictionary<string,int>
和(已排序)List<string>
之间差异的小概述:
观察:
1)在我的微基准测试中,一旦创建了字典,字典就会快得多。 (关于为什么会很快跟进的说明)
2)在我看来,以某种方式进行映射(例如,Dictionary
或HashTable
)将不那么尴尬。
性能:
对于List<string>
,要进行二分搜索,系统将从“中间”开始,然后走向每个方向(步入现在减半的搜索空间中的“中间”,在典型的鸿沟中征服模式)取决于该值是大于还是小于它正在查看的索引处的值。这是O(log n)
增长。这假设数据已经以某种方式排序(也适用于SortedDictionary
之类的东西,它使用允许二进制搜索的数据结构)
或者,您需要执行IndexOf
,这是O(n)
复杂度,因为您必须遍历每个元素。
对于Dictionary<string,int>
,它使用哈希查找(通过调用.GetHashCode()
上的TKey
生成对象的哈希值(本例中为字符串),然后使用它查找在哈希表中(然后进行比较以确保它是精确匹配),并获得值。这大约是O(1)
增长(即复杂性不会随着元素的数量而有意义地增长)[不包括涉及哈希冲突的最坏情况场景]
因此,Dictionary<string,int>
需要(相对)恒定的时间来进行查找,而List<string>
根据元素的数量增长(尽管是以对数(慢)速率)。 / p>
测试: 我做了一些微基准测试,在那里我获得了前500名的女性名字并对他们进行了查找。查找看起来像这样:
var searchItems = new[] { "Maci", "Daria", "Michelle", "Amber", "Henrietta"};
foreach (var item in searchItems)
{
sortedList.BinarySearch(item); //You'd store the output here. Just looking at performance
}
并将其与字典查找进行比较:
foreach (var item in searchItems)
{
var output = dictionary.ContainsKey(item) ? dictionary[item] : -1; //Presumably, output would be declared outside of this, just getting rid of a compiler error
}
所以,这就是事情:即使对于少量的元素,使用短字符串作为查找键,排序的List<string>
也不是更快(在我的机器上,在我公认的简单测试中)而不是{ {1}}。再一次,这是一个微基准测试,但对于500个元素,使用字典,5个查找速度大约快3倍。
但请注意,列表为6.3 微秒,字典为1.8 微秒。
语法:
使用列表作为查找来查找索引有点尴尬。映射类型(如Dictionary<string,int>
)意味着意图比查找列表更好,这最终会使代码更易于维护。
那就是说,根据我的语法和性能考虑因素,我会说与词典一起使用。但是,如果你因为某种原因不喜欢字典,那么性能考虑因素就会很小,无论如何都要担心它是无意义的。
编辑:奖励积分,您可能希望对任一方法使用不区分大小写的比较器。您可以将比较器作为Dictionary
的参数传递,Dictionary
也应支持比较器。
答案 1 :(得分:3)
我怀疑某处可能会出现扭曲,因为这样一个简单的问题在2小时内没有答案。我冒着被投票的风险,但这是我的答案:
1)字典(基于哈希表)显然是快速查找的更好选择。另一方面,列表是最糟糕的选择。
1.b)是的,它适用于此处。列表中的搜索具有线性复杂性,而词典提供恒定时间查找。
2)您正在尝试将字符串映射到序数;任何类型的地图都是自然的(虽然任何类型的列表都很尴尬)。
答案 2 :(得分:2)
字典是查找的自然方法。
列表将是以降低速度为代价减少内存使用的优化。数组会做得更好(同时,但内存会稍微减少)。
如果由于某些其他原因你已经有了一个列表或数组,那么内存节省会更大,因为不再使用将会使用的内存,因此以相同的速度优化空间以加快速度。 (如果键的顺序与排序相同则可以是O(log n),否则它是O(n))。
创建字典本身需要时间,所以虽然它是最快的方法,如果它被查找的次数很少,那么它可能会节省成本,因此不值得。