Получить индекс пары ключ / значение в словаре C # на основе значения - PullRequest
34 голосов
/ 27 декабря 2010

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

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

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

Ответы [ 8 ]

31 голосов
/ 27 декабря 2010

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

Очевидно, что вы можете получить ключ от 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 будет нулевым, если запись не существует.

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

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

21 голосов
/ 29 августа 2015

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

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

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

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

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

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

9 голосов
/ 27 декабря 2010

Подумайте об использовании 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;
    }
}
2 голосов
/ 27 декабря 2010

Вы можете использовать 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
1 голос
/ 11 июля 2018
    You can find index by key/values in dictionary
Dictionary<string, string> myDictionary = new Dictionary<string, string>();
myDictionary.Add("a", "x");
myDictionary.Add("b", "y");
int i = Array.IndexOf(myDictionary.Keys.ToArray(), "a");
int j = Array.IndexOf(myDictionary.Values.ToArray(), "y");
1 голос
/ 27 декабря 2010

При поиске значения, вам придется перебирать все данные .Но для минимизации кода можно использовать 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;
0 голосов
/ 06 октября 2017

В своем комментарии к max s answer вы говорите, что действительно хотите получить key in, а not the index of, KeyValuePair, которая содержит определенное значение. Вы можете отредактировать свой вопрос, чтобы сделать его более понятным.

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

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

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

yourDictionary.ElementAt(theIndexYouFound);

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

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

0 голосов
/ 27 декабря 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...