情况如下:
ConcurrentDictionary<TId, TItem>
我想出的最好方法是:
public IEnumerable<TItem> Get( TId fromKey, int count )
{
// parameter validation left out for brevity
return items.Keys // KeyCollection of the Dictionary, please assume 'items' is a class field
.SkipWhile(key => key != fromKey)
.Take(count)
.Select(x => items[x])
.ToList();
}
但这感觉真的不对。特别是因为我们明确不想“SkipWhile”。如果我可以跳过,我可以做
.Skip(n).Take(m)
值,但这显然不是想要的。对我的要求是:从键K开始,返回N个元素。也许我想得太多了,我应该退缩。但我有一种感觉,我在这里错过了一些东西。
所以我的问题是:有没有办法做到这一点,而不必在字典的 KeyCollection 或 ValueCollection 中“跳过”?
编辑
ConcurrentDictionary<TKey, TVaue>
是我接任务的地方。它不是刻在石头上来保持那种类型的。 最佳答案
嗯,根据评论,这听起来有点奇怪,但我相信有一些原因你不能进入背景故事或细节。
我会说这个。SkipWhile(key => key != fromKey)
确实是您可以找到 key 以在“之后”找到更多 key 的唯一方法,因此从这个意义上说,您拥有的是正确的。如果您的 key 空间不是大得离谱,那似乎就足够了。
也就是说,不同的数据结构会更好。例如,您可以实现字典 + 数组或字典 + 链表的并发版本,允许您访问 O(1) 中的键,然后访问 lock
中 O(m) 中的后续元素。 (您甚至可以将其设为 ReaderWriterLockSlim
)。这避免了 O(n)
如果只是使用 ConcurrentDictionary
扫描以找到 key .
插入会有点奇怪,因为您必须对前后的含义保持某种随意的概念。例如,在字典 + 数组的情况下,您可以将键 'foo' 添加到字典和数组中的槽 0 中。键 'bar' 会像往常一样进入字典,然后进入插槽 1,依此类推。
哦 - 你的字典条目必须指向数组或链表中的位置才能获得 O(m) 以及数据本身。而且,如果您想对数据进行重复数据删除,数组/列表可以指向字典条目,而不仅仅是保存数据。
当项目被删除时,数组会给你留下漏洞!这就是链表有用的地方。保持“排序”(松散地使用这个术语)并且因为您正在访问两个底层数据结构,写入会有点慢。
关于c# - ConcurrentDictionary<TKey, TValue> - 如何有效地 "get N elements, starting from key K"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66278234/