简体   繁体   中英

C# get keys and values from List<KeyValuePair<string, string>

Given a list:

    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"));
    }

(NOTE: there are multiple values for the key "qwer" and multiple keys for the value "asdf".)

1) Is there a better way to return a list of all keys than just doing a foreach on the KeyValuePair List?

2) Similarly, is there a better way to return a list of all values for a given key than using a foreach?

3) And then, how about returning a list of keys for a given value?

Thanks...

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

It sounds like you would benefit from using something like:

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
}

It would be relatively easy to create a basic mutli-value dictionary class using a Dictionary and List.

This blog post talks more about Microsoft's MultiDictionary type available via NuGet.

You can use NameValueCollection from System.Collection.Specialized namespace:

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");

Example of use:

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

Well you could definitly use your LINQ. But it's not "better" (in term of performance) since looping is already fast. It is perhaps more readable (personnal preference). For all the answers below, be aware that you need to have the System.Linq namespace imported. They also return IEnumerable<T> that are lazy loaded (executed when iterated over). If you want to return a concrete list, you can call the .ToList() extension .

Is there a better way to return a list of all keys than just doing a foreach on the KeyValuePair List?

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

Similarly, is there a better way to return a list of all values for a given key than using a foreach?

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

And then, how about returning a list of keys for a given value?

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

For more information on LINQ, look at LINQ (Language-Integrated Query)

I would use ILookup<K,V> in your case. It is like a dictionary but you can get the values as IEnumerable<V> with the same key.

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);
}

or simply

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

Are you reading this and wondering why someone made some code have an IEnumerable<KeyValuePair<A,B>> instead of a Dictionary<A,B> but don't feel like asking and just want to get done?

if (collection == null)
    return null;

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM