7

如何Enumerator使用键获取 -Sorted- 字典中的项目?

注意:GetEnumerator()获取Enumerator第一个元素..

但是我需要使用给定键获取元素,以便使用例如...Enumerator访问下一个元素MoveNext()

编辑:或者访问下一个元素的方法......

编辑:我更喜欢 const time 方法...

谢谢

4

6 回答 6

9
var enumerator = dictionary.Keys.SkipWhile(k => k != myKey)

Where myKey is the key you're looking for. And you can use the OrderBy extension method if you want to have the keys sorted.

Edit: You can't do it in constant with Dictionary/SortedDictionary. Why not implement your own binary search tree (like SortedDictionary is) and you will have O(log n) time lookup and O(1) time .next()?

于 2010-07-27T10:04:23.390 回答
2

也许这对某人有用:

public Dictionary<string, int> myDictionary = new Dictionary<string, int>();
public string myCurrentKey = "some key 5";
for (int i = 1; i <= 10; i++) {
    myDictionary.Add(string.Format("some key {0}", i), i);
}

private void MoveIndex(int dir) { // param "dir" can be 1 or -1 to move index forward or backward
    List<string> keys = new List<string>(myDictionary.Keys);
    int newIndex = keys.IndexOf(myCurrentKey) - dir;
    if (newIndex < 0) {
        newIndex = myDictionary.Count - 1;
    } else if (newIndex > myDictionary.Count - 1) {
        newIndex = 0;
    }

    myCurrentKey = keys[newIndex];
}

Debug.Log(string.Format("Current value: {0}", myDictionary[myCurrentKey])); // prints 5
MoveIndex(1);
Debug.Log(string.Format("Current value: {0}", myDictionary[myCurrentKey])); // prints 6
MoveIndex(-1);
MoveIndex(-1);
Debug.Log(string.Format("Current value: {0}", myDictionary[myCurrentKey])); // prints 4
于 2013-08-18T08:05:55.040 回答
1

You can't do that with Dictionary. You can accomplish that having possibility of accessing by index, so you can use SortedList instead of Dictionary. Also you can have a look at SkipWhile.

Although you can have some workaround like this :

Dictionary<int, int> dictionary = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> pair in dictionary)
{ 
   // you can check the key you need and assume that the next one will be what you need.
}

But of course this is not the best idea.

于 2010-07-27T10:06:53.127 回答
1

如果您安装了 Framework >=3.5,请使用建议的SkipWhile Janus Tondering 和 LukeH。对于较低的框架版本,您必须自己完成(fe 用从您的键到末尾的键值对填充第二个字典)。

于 2010-07-27T10:23:31.853 回答
0

最简单的选择是使用 aSortedList然后向其添加一个扩展方法,该方法返回一个IEnumerable元素大于或等于给定键的元素。下面的方法的复杂度GetElementsGreaterThanOrEqual是 O(log(n)) 来获取第一个元素,然后每次迭代都是 O(1)。

public static class SortedListExtension
{
    public static IEnumerable<KeyValuePair<TKey, TValue>> GetElementsGreaterThanOrEqual<TKey, TValue>(this SortedList<TKey, TValue> instance, TKey target) where TKey : IComparable<TKey>
    {
        int index = instance.BinarySearch(target);
        if (index < 0)
        {
            index = ~index;
        }
        for (int i = index; i < instance.Count; i++)
        {
            yield return new KeyValuePair<TKey, TValue>(instance.Keys[i], instance.Values[i]);
        }
    }

    public static int BinarySearch<TKey, TValue>(this SortedList<TKey, TValue> instance, TKey target) where TKey : IComparable<TKey>
    {
        int lo = 0;
        int hi = instance.Count - 1;
        while (lo <= hi)
        {
            int index = lo + ((hi - lo) >> 1);
            int compare = instance.Keys[index].CompareTo(target);
            if (compare == 0)
            {
                return index;
            }
            else
            {
                if (compare < 0)
                {
                    lo = index + 1;
                }
                else
                {
                    hi = index - 1;
                }
            }
        }
        return ~lo;
    }
}
于 2010-07-27T15:01:05.683 回答
0
var query = yourDictionary.SkipWhile(kvp => kvp.Key != keyToFind);
foreach (var result in query)
{
    // ...
}
于 2010-07-27T10:07:00.060 回答