В C# получить ключи и значения из списка

приведенный список:

    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), а затем, как насчет возврата списка ключей для данного ценность?

спасибо...

7 ответов


// #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" }

похоже, вы выиграете от использования чего-то вроде:

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
}

было бы относительно легко создать базовый класс словаря mutli-value, используя словарь и список.

этой блоге подробнее о Мультидикционном типе Microsoft, доступном через NuGet.


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

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

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

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

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)


Вы можете использовать NameValueCollection из системы.Коллекция.Специализированное пространство имен:

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


Я хотел бы использовать 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"]));

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()

Вы читаете это и задаетесь вопросом, почему кто-то сделал какой-то код с IEnumerable> вместо словаря, но не хотите спрашивать и просто хотите сделать?

if (collection == null)
    return null;

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