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

LINQ: получение ключей для данного списка значений из словаря и наоборот

У меня есть следующая структура в моем коде Dictionary<TKeys, TValues> data;. Я запускаю некоторые запросы LINQ для обоих типов данных и часто должен переключаться между Keys и Values. Каков наилучший способ получить список ключей для заданных значений и наоборот? Пожалуйста, обратите внимание, что я обычно имею "IEnumerable" и "IEnumerable" в результате моих предыдущих запросов LINQ и хотел бы иметь что-то вроде IEnumerable<TKeys> Dictionary.GetAllKeys(IEnumerable<IValues> vals) и IEnumerable<TValues> Dictionary.GetAllValues(IEnumerable<IKeys> keys).

Может мне понадобится другой контейнер данных для этой задачи?

С уважением, Александр.

4b9b3361

Ответ 1

 var values = dictionary.Where(x => someKeys.Contains(x.Key)).Select(x => x.Value);
 var keys = dictionary.Where(x => someValues.Contains(x.Value)).Select(x => x.Key);

Ответ 2

A Dictionary<,> действительно не подходит для поиска ключей по значению. Вы можете написать двунаправленный словарь, как который я сделал в этом ответе, но это не обязательно лучший подход.

Конечно, вы можете использовать словарь как последовательность пар ключ/значение, чтобы вы могли:

var keysForValues = dictionary.Where(pair => values.Contains(pair.Value))
                              .Select(pair => pair.Key);

Просто помните, что это будет операция O (n), даже если ваши "значения" являются HashSet или что-то подобное (с эффективной проверкой сдерживания).

EDIT: Если вам действительно не нужно отношение ключ/значение - если оно больше похоже на пары, то использование List<Tuple<Foo, Bar>> будет иметь определенный смысл. Запрос заканчивается тем же, в основном:

public IEnumerable<T1> GetAllFirst<T1, T2>(IEnumerable<Tuple<T1, T2>> source,
                                           IEnumerable<T2> seconds)
{
    HashSet<T2> secondsSet = new HashSet<T2>(seconds);
    return source.Where(pair => secondsSet.Contains(pair.Item2));
}

public IEnumerable<T2> GetAllSecond<T1, T2>(IEnumerable<Tuple<T1, T2>> source,
                                            IEnumerable<T1> firsts)
{
    HashSet<T1> firstsSet = new HashSet<T1>(firsts);
    return source.Where(pair => firstsSet.Contains(pair.Item1));
}

Ответ 3

Лучший подход - выполнить ваш запрос linq в коллекции пар ключ-значение, а затем использовать Select Select для выбора ключей или значений в конце вашего запроса. Таким образом, нет необходимости выполнять поиск в конце вашего запроса.

Например:

  Dictionary<string, string> data = new Dictionary<string, string>();
  // select all values for keys that contain the letter 'A'
  var values = data.Where(pair => pair.Key.Contains("A"))
                   .Select(pair => pair.Value);