简体   繁体   中英

How to get keys from the dictionary if value is in List form?

I have a dictionary named as dict_id_names :

Dictionary<int,List<string>> dict_id_names = new Dictionary<int,List<string>();

Suppose dictionary contains 3 key-value pairs:

  • id = 1 : List contains names "Robin", "Rahul", "Adam", "Akhtar",

  • id = 2 : List contains names "Sun", "Mon", "Adam",

  • id = 3 : List contains names "a", "b", "c"

Now my question is that if I only have name "Adam" then how can I get the respective key / keys as 1 and 2 in the above case from the dictionary?

You can use LINQ:

var keyValsWithAdamValue = dict_id_names.Where(kv => kv.Value.Contains("Adam"));

foreach(var kv in keyValsWithAdamValue)
    Console.WriteLine("{0}|{1}", kv.Key, String.Join(",", kv.Value));

If you just want the ID s you can select them and use ToList / ToArray to create a collection:

List<int> idsWithAdamInList = dict_id_names
    .Where(kv => kv.Value.Contains("Adam"))
    .Select(kv => kv.Key)
    .ToList();

Note that this approach is like a loop over the dictionary. You don't benefit from the fast lookup performance of a dictionary if you're enumerating it. It's not designed for this purpose. But it's simple and readable code and perfect if performance is not so important in this case.

You can use the following LINQ query:

int[] ids = dict_id_names
                    .Where(pair => pair.Value.Contains("Adam"))
                    .Select(pair => pair.Key)
                    .ToArray();

Console.WriteLine(String.Join(',', ids)); // 1,2

It will result in an array [1, 2] , because both of these dictionary entries contain Adam in its string list.

string name = "Adam";
foreach(int key in dict_id_names.Keys)
{
    List<string> valueList = dict_id_names[key];

    if(valueList.Contains(name);
       Console.WriteLine(id);
}

This should help.

Something like -

var dict_id_names= new Dictionary<int,List<string>>();
dict_id_names.Add(1, new List<string> { "Robin", "Rahul", "Adam", "Akhtar" });
var id = dict_id_names.Where(a => a.Value.Contains("Adam")).FirstOrDefault().Key;

I'd just like to offer a different perspective, for comparative purposes.

Suppose that you are doing this reverse lookup frequently, and you want it to be better than an O(N) operation.

You can achieve that using two dictionaries instead of one. To simplify things in this example, I'll use Microsoft's pre-release MultiValueDictionary (which you can obtain via NuGet).

This approach yields an O(1) lookup:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    internal class Program
    {
        public static void Main()
        {
            var names = new Names();

            names.Add(1, "Robin");
            names.Add(1, "Rahul");
            names.Add(1, "Adam");
            names.Add(1, "Akhtar");

            names.Add(2, "Sun");
            names.Add(2, "Mon");
            names.Add(2, "Adam");

            names.Add(3, "a");
            names.Add(3, "a");
            names.Add(3, "c");

            Console.WriteLine("IDs for Adam:");

            foreach (int id in names.IdsOf("Adam"))
                Console.WriteLine(id);
        }

        public sealed class Names
        {
            readonly MultiValueDictionary<int, string> names = new MultiValueDictionary<int, string>();
            readonly MultiValueDictionary<string, int> lookup = new MultiValueDictionary<string, int>();

            public void Add(int id, string name)
            {
                names.Add(id, name);
                lookup.Add(name, id);
            }

            public IEnumerable<int> IdsOf(string name)
            {
                IReadOnlyCollection<int> result;

                if (lookup.TryGetValue(name, out result))
                    return result;
                else
                    return Enumerable.Empty<int>();
            }

            public IEnumerable<string> NamesOf(int id)
            {
                IReadOnlyCollection<string> result;

                if (names.TryGetValue(id, out result))
                    return result;
                else
                    return Enumerable.Empty<string>();
            }
        }
    }
}

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