Подтвердить что ты не робот

Получить индекс пары ключ/значение в словаре С# на основе значения

Я хотел бы знать, существует ли какое-либо свойство или метод, который получает индекс определенного значения.

Я обнаружил, что словари имеют метод Contains(), который возвращает true, если переданное значение существует, поэтому этот метод почти реализует то, что мне нужно.

Я знаю, что я могу пройти через все пары значений и проверить условие, но я прошу, потому что возможно оптимизированный способ сделать это.

4b9b3361

Ответ 1

В словаре нет такого понятия "индекса" - оно в корне неупорядочено. Конечно, когда вы перебираете его, вы получите предметы в определенном порядке, но этот порядок не гарантируется и может меняться со временем (особенно если вы добавляете или удаляете записи).

Очевидно, вы можете получить ключ от KeyValuePair только с помощью свойства Key, так что вы сможете использовать индексатор словаря:

var pair = ...;
var value = dictionary[pair.Key];
Assert.AreEqual(value, pair.Value);

Вы действительно не сказали, что вы пытаетесь сделать. Если вы пытаетесь найти какой-то ключ, который соответствует определенному значению, вы можете использовать:

var key = dictionary.Where(pair => pair.Value == desiredValue)
                    .Select(pair => pair.Key)
                    .FirstOrDefault();

Key будет пустым, если запись не существует.

Это предполагает, что тип ключа является ссылочным типом... если это тип значения, вам нужно будет делать что-то немного по-другому.

Конечно, если вы действительно хотите искать значения по ключу, вам следует рассмотреть возможность использования другого словаря, который отображает другой способ в дополнение к вашему существующему словарю.

Ответ 2

Рассмотрите возможность использования System.Collections.Specialized.OrderedDictionary, хотя он не является общим или не реализует ваш собственный (пример).

OrderedDictionary не поддерживает IndexOf, но его легко реализовать:

public static class OrderedDictionaryExtensions
{
    public static int IndexOf(this OrderedDictionary dictionary, object value)
    {
        for(int i = 0; i < dictionary.Count; ++i)
        {
            if(dictionary[i] == value) return i;
        }
        return -1;
    }
}

Ответ 3

Скажем, у вас есть словарь под названием fooDictionary

fooDictionary.Values.ToList().IndexOf(someValue);

Values.ToList() преобразует значения словаря в список объектов someValue.

IndexOf (SomeValue) ищет новый список, ищущий объект someValue и возвращает индекс, который будет соответствовать индексу пары Key/Value в словаре.

Этот метод не заботится о словарных ключах, он просто возвращает индекс значения, которое вы ищете.

Это, однако, не учитывает проблему, что может быть несколько подходящих объектов someValue.

Ответ 4

Вы можете использовать LINQ, чтобы помочь вам в этом.

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "hi");
dict.Add(2, "NotHi");
dict.Add(3, "Bah");

var item = (from d in dict
            where d.Value == "hi"
            select d.Key).FirstOrDefault();

Console.WriteLine(item); //Prints 1

Ответ 5

Если вы ищете значение, , вам придется перебирать все данные. Но чтобы свести к минимуму задействованный код, вы можете использовать LINQ.

Пример:

Данный словарь определяется следующим образом:

Dictionary<Int32, String> dict;

Вы можете использовать следующий код:

// Search for all keys with given value
Int32[] keys = dict.Where(kvp => kvp.Value.Equals("SomeValue")).Select(kvp => kvp.Key).ToArray();

// Search for first key with given value
Int32 key = dict.First(kvp => kvp.Value.Equals("SomeValue")).Key;

Ответ 6

нет, нет ничего подобного IndexOf для словаря, хотя вы можете использовать метод ContainsKey для получения того, принадлежит ли ключ к словарю или нет

Ответ 7

В своем комментарии к max ответьте, что вы действительно хотели получить ключ , а не индекс KeyValuePair, который содержит определенное значение. Вы можете изменить свой вопрос, чтобы сделать его более понятным.

Стоит отметить (EricM затронул это в ответе ), что значение может появляться более одного раза в словаре, и в этом случае нужно было бы подумать, какой ключ он хотел бы получить: например первое, что подходит, последнее, все из них?

Если вы уверены, что каждая клавиша имеет уникальное значение, у вас может быть другой словарь со значениями от первого, действующего как клавиши, и предыдущими клавишами, действующими в качестве значений. В противном случае эта вторая идея словаря (предлагаемая Jon Skeet) не будет работать, так как вам снова придется подумайте, какой из всех возможных ключей использовать в качестве значения в новом словаре.

Если бы вы спрашивали об индексе, ответ EricM был бы в порядке. Затем вы можете получить ключ KeyValuePair, используя:

yourDictionary.ElementAt(theIndexYouFound);

при условии, что вы не добавляете/не удаляете вещи в yourDictionary.

PS: Я знаю, что это было почти 7 лет, но что за черт. Я подумал, что лучше всего сформулировать свой ответ как обращение к OP, но, конечно, теперь можно сказать, что это ответ практически для кого-то другого, кроме OP. Полностью осознавая это, спасибо.