Получить индекс пары ключ/значение в словаре С# на основе значения
Я хотел бы знать, существует ли какое-либо свойство или метод, который получает индекс определенного значения.
Я обнаружил, что словари имеют метод Contains()
, который возвращает true, если переданное значение существует, поэтому этот метод почти реализует то, что мне нужно.
Я знаю, что я могу пройти через все пары значений и проверить условие, но я прошу, потому что возможно оптимизированный способ сделать это.
Ответы
Ответ 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. Полностью осознавая это, спасибо.