简体   繁体   English

快速找到SortedDictionary中第一个未使用的密钥?

[英]Fast way to find the first unused key in a SortedDictionary?

If I have a SortedDictionary<int, object> , what is the fastest way to find the lowest key that is not currently being used? 如果我有一个SortedDictionary<int, object> ,找到当前没有使用的最低密钥的最快方法是什么? Obviously, we could iterate a counter i from 0-> int.MaxValue and escape if !Keys.Contains(i) , but that would be very slow unless we were lucky and the first spare key happened to be early on in the sequence of keys. 显然,我们可以从0-> int.MaxValue迭代一个计数器i并且如果!Keys.Contains(i)转义,但是除非我们很幸运并且第一个备用键碰巧是在序列的早期,否则这将是非常缓慢的。键。 Maybe even a different .NET class does this for us already? 也许甚至一个不同的.NET类已经为我们这样做了?

So, If I understand you correctly, the keys can be anywhere from 0 to int.MaxValue . 所以,如果我理解正确,那么键可以是从0int.MaxValue任何地方。 In that case, you have to find the first "hole" in the sequence of keys. 在这种情况下,你必须找到键序列中的第一个“洞”。

This should do the job efficiently: 这应该有效地完成工作:

public static int GetFirstUnusedKey<TValue>(SortedDictionary<int, TValue> dict)
{
    if (dict.Comparer != Comparer<int>.Default)
        throw new NotSupportedException("Unsupported comparer");

    using (var enumerator = dict.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            return 0;

        var nextKeyInSequence = enumerator.Current.Key + 1;

        if (nextKeyInSequence < 1)
            throw new InvalidOperationException("The dictionary contains keys less than 0");

        if (nextKeyInSequence != 1)
            return 0;

        while (enumerator.MoveNext())
        {
            var key = enumerator.Current.Key;
            if (key > nextKeyInSequence)
                return nextKeyInSequence;

            ++nextKeyInSequence;
        }

        return nextKeyInSequence;
    }
}

I added a couple of checks to ensure the preconditions are valid. 我添加了几项检查以确保前提条件有效。

Why not a binary search on the keys? 为什么不在键上进行二进制搜索?

You can use ElementAt() method to identify the key value at an index. 您可以使用ElementAt()方法来标识索引处的键值。 If the key value is greater than the index, then search in the left sub dictionary or choose the right and go on that way till you find the index at which you observe the first difference between index and the value at the index. 如果键值大于索引,则在左子词典中搜索或选择右侧词典并继续,直到找到索引与索引值之间的第一个差异的索引。

I'm not claiming any sort of performance trophy for this approach, but I think it goes someway towards achieving your aim: 我没有为这种方法申请任何表现奖杯,但我认为它在实现你的目标方面取得了一些进展:

var sd = new SortedDictionary<int, object>();

sd.Add(1, 1);
sd.Add(2, 1);
sd.Add(4, 1);
sd.Add(5, 1);

var e = Enumerable.Range(1, 5).Except(sd.Keys).First();

e = 3 in this case, as intended. 在这种情况下,e = 3,如预期的那样。 I would expect that there are better solutions, though. 不过,我希望有更好的解决方案。

Do not search for a unused key starting at 0. 不要搜索从0开始的未使用的密钥。

Instead iterate the used keys, starting at the lowest (they are sorted). 而是从最低处开始迭代使用过的密钥(它们已排序)。

Either the first is >0 then 0 is your lowest unused. 要么第一个> 0,那么0是未使用的最低值。

or there is a gap between two keys, then lower+1 is what you searched for. 或者两个键之间有间隙,然后低于+ 1是您搜索的内容。

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

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