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