Следующий ключ в словаре C # - PullRequest
7 голосов
/ 27 июля 2010

Как получить Enumerator для элемента в -Sorted- словаре, используя ключ?

Примечание: GetEnumerator() получает Enumerator для первого элемента.

Но мне нужно получить Enumerator для элемента с данным ключом, чтобы получить доступ к следующим элементам, используя, например, MoveNext() ...

Редактировать: Или способ доступа к следующим элементам ...

Редактировать: Я предпочитаю метод постоянного времени ...

Спасибо

Ответы [ 6 ]

8 голосов
/ 27 июля 2010
var enumerator = dictionary.Keys.SkipWhile(k => k != myKey)

Где myKey - это ключ, который вы ищете.И вы можете использовать метод расширения OrderBy, если хотите отсортировать ключи.

Редактировать : вы не можете делать это постоянно с Dictionary / SortedDictionary.Почему бы не реализовать собственное двоичное дерево поиска (как SortedDictionary is), и у вас будет O (log n) поиск времени и O (1) время .next()?

1 голос
/ 18 августа 2013

Может быть, это кому-нибудь пригодится:

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
1 голос
/ 27 июля 2010

Если у вас установлен Framework> = 3.5, используйте SkipWhile Предлагаются Janus Tondering и LukeH. Для более ранних версий фреймворка вы должны сделать это для себя (например, заполните второй словарь парой значений ключей от вашего ключа до конца).

1 голос
/ 27 июля 2010

Вы не можете сделать это с помощью Dictionary . Вы можете добиться этого, имея возможность доступа по индексу, так что вы можете использовать SortedList вместо словаря. Также вы можете взглянуть на SkipWhile .

Хотя вы можете иметь обходной путь, подобный этому:

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.
}

Но, конечно, это не лучшая идея.

0 голосов
/ 27 июля 2010

Самый простой вариант - использовать SortedList, а затем добавить к нему метод расширения, который возвращает 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;
    }
}
0 голосов
/ 27 июля 2010
var query = yourDictionary.SkipWhile(kvp => kvp.Key != keyToFind);
foreach (var result in query)
{
    // ...
}
...