2015-07-14 5 views
7

Учитывая список:C# получить ключи и значение из списка <KeyValuePair <строки, строка>

private List<KeyValuePair<string, string>> KV_List = new List<KeyValuePair<string, string>>(); 
    void initList() 
    { 
     KV_List.Add(new KeyValuePair<string, string>("qwer", "asdf")); 
     KV_List.Add(new KeyValuePair<string, string>("qwer", "ghjk")); 
     KV_List.Add(new KeyValuePair<string, string>("zxcv", "asdf")); 
     KV_List.Add(new KeyValuePair<string, string>("hjkl", "uiop")); 
    } 

(Примечание: Есть несколько значений для ключа «QWER» и нескольких ключей для «ASDF» значения .)

1) Есть ли лучший способ вернуть список всех ключей, чем просто сделать foreach в списке KeyValuePair?

2) Точно так же есть лучший способ вернуть список всех значений для данного ключа, чем использовать foreach?

3) И затем, как насчет возврата списка ключей для заданного значения?

Благодаря ...

+0

Можете ли вы использовать multimap как [this] (http://stackoverflow.com/questions/380595/multimap-in-net)? – ntohl

ответ

11
// #1: get all keys (remove Distinct() if you don't want it) 
List<string> allKeys = (from kvp in KV_List select kvp.Key).Distinct().ToList(); 
// allKeys = { "qwer", "zxcv", "hjkl" } 

// #2: get values for a key 
string key = "qwer"; 
List<string> values = (from kvp in KV_List where kvp.Key == key select kvp.Value).ToList(); 
// values = { "asdf", "ghjk" } 

// #3: get keys for a value 
string value = "asdf"; 
List<string> keys = (from kvp in KV_List where kvp.Value == value select kvp.Key).ToList(); 
// keys = { "qwer", "zxcv" } 
+0

Как использовать то же самое для динамического списка – Sam

0

1:

KV_List.Select(i => i.Key).ToList() 

2:

KV_List.Where(i => i.Key == filterByKey).Select(i => i.Value).ToList() 

3:

KV_List.Where(i => i.Value == filterByValue).Select(i => i.Key).ToList() 
5

Это Soun DS, как вы бы извлечь выгоду из использования что-то вроде:

Dictionary<string, List<string>> kvlist; 

kvlist["qwer"] = new List<string>(); 
kvlist["qwer"].Add("value1"); 
kvlist["qwer"].Add("value2"); 

foreach(var value in kvlist["qwer"]) { 
    // do something 
} 

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

Этот blog post подробно рассказывает о Microsoft MultiDictionary, доступном через NuGet.

+0

К сожалению, у меня нет контроля над списком (мне нужно «воспроизвести его, как он лежит») ... –

+0

А - это отстой. Некоторые ответы на основе Linq должны делать то, что вы хотите (хотя они будут более синтаксически дружественными, они не будут более эффективными, чем просто цикл). Если вы можете убедиться, что список всегда сортируется по значению ключа, вы можете повысить производительность от O (n) до O (log n). –

+0

Обычно он несортирован (либо по ключу, либо по значению), однако в списке всего несколько тысяч записей. Я, вероятно, выберу один из ответов linq, и они будут «выглядеть» чище для всех, кто смотрит на код в будущем. :) –

2

Вы можете использовать NameValueCollection из System.Collection.Specialized имен:

NameValueCollection KV_List = new NameValueCollection(); 

KV_List.Add("qwer", "asdf"); 
KV_List.Add("qwer", "ghjk"); 
KV_List.Add("zxcv", "asdf"); 
KV_List.Add("hjkl", "uiop"); 

Пример использования:

string singleValue = KV_List["zxcv"]; // returns "asdf" 
string[] values = KV_List.GetValues("qwer"); // returns "asdf, "ghjk" 
string[] allKeys = KV_List.AllKeys; 
string[] allValues = KV_List.AllKeys; 

https://msdn.microsoft.com/en-us/library/system.collections.specialized.namevaluecollection%28v=vs.110%29.aspx

2

Ну вы могли бы определенно использовать LINQ. Но это не «лучше» (с точки зрения производительности), поскольку цикл уже идет быстро. Возможно, это более читаемо (личное предпочтение). Для всех ответов ниже, имейте в виду, что вам нужно импортировать пространство имен System.Linq. Они также возвращают IEnumerable<T>, которые лениво загружаются (выполняются при повторении). Если вы хотите вернуть конкретный список, вы можете позвонить .ToList() extension.

Есть ли лучший способ вернуть список всех ключей, чем просто сделать foreach в списке KeyValuePair?

KV_List.Select(kvp => kvp.Key); 

Аналогично, есть лучший способ вернуть список всех значений для данного ключа, чем при использовании Еогеасп?

var theKeyToLookFor = "qwer"; 
KV_List.Where(kvp => kvp.Key == theKeyToLookFor).Select(kvp => kvp.Value); 

А потом, как насчет возвращения списка ключей для данного значения?

var theValueToLookFor = "asdf"; 
KV_List.Where(kvp => kvp.Value == theValueToLookFor) 
     .Select(kvp => kvp.Value) 
     .ToList(); 

Для получения дополнительной информации о LINQ, смотрите на LINQ (Language-Integrated Query)

1

Я хотел бы использовать ILookup<K,V> в вашем случае. Это похоже на словарь, но вы можете получить значения как IEnumerable<V> с тем же ключом.

ILookup<string, string> lookup = KV_List.ToLookup(x => x.Key, x => x.Value); 
IEnumerable<string> list = lookup["qwer"]; 
foreach(string str in list) 
{ 
    Console.WriteLine(str); 
} 

или просто

Console.WriteLine(string.Join(",", lookup["qwer"])); 
0

Вы читаете это и интересно, почему кто-то сделал какой-то код есть IEnumerable < KeyValuePair < A, B > > вместо словарь < A, B >, но дон» Чувствуешь, что спрашиваешь и просто хочешь сделать?

if (collection == null) 
    return null; 

return collection 
    .Where(z => z.Key == aThing) 
    .Select(z => z.Value) 
    .FirstOrDefault();