【问题标题】:How to get keys from the dictionary if value is in List form?如果值是列表形式,如何从字典中获取键?
【发布时间】:2015-11-05 09:04:23
【问题描述】:

我有一本名为dict_id_names的字典:

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

假设字典包含 3 个键值对:

  • id = 1:列表包含名称“Robin”、“Rahul”、“Adam”、“Akhtar”,

  • id = 2:列表包含名称“Sun”、“Mon”、“Adam”,

  • id = 3:列表包含名称“a”、“b”、“c”

现在我的问题是,如果我只有名字“Adam”,那么在上述情况下,如何从字典中获取相应的键/键为 1 和 2?

【问题讨论】:

  • 是否需要像普通字典一样反向查找~O(1)?请注意,以下所有答案都涉及对字典的全面扫描。

标签: c# dictionary


【解决方案1】:

您可以使用 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));

如果您只想要IDs,您可以选择它们并使用ToList/ToArray 创建一个集合:

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

请注意,这种方法类似于字典上的循环。如果您枚举它,您不会从字典的快速查找性能中受益。它不是为此目的而设计的。但如果在这种情况下性能不是那么重要,那么它是简单易读的代码。

【讨论】:

    【解决方案2】:

    您可以使用以下 LINQ 查询:

    int[] ids = dict_id_names
                        .Where(pair => pair.Value.Contains("Adam"))
                        .Select(pair => pair.Key)
                        .ToArray();
    
    Console.WriteLine(String.Join(',', ids)); // 1,2
    

    这将产生一个数组[1, 2],因为这两个字典条目都在其字符串列表中包含Adam

    【讨论】:

      【解决方案3】:
      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);
      }
      

      这应该会有所帮助。

      【讨论】:

      • 是的,我之前试过这个,但是有没有其他方法或方法不需要全面扫描字典?
      【解决方案4】:

      类似的东西-

      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;
      

      【讨论】:

        【解决方案5】:

        我只是想提供一个不同的观点,以进行比较。

        假设您经常进行这种反向查找,并且您希望它比 O(N) 操作更好。

        您可以使用两个字典而不是一个字典来实现这一点。为了简化此示例中的内容,我将使用 Microsoft 的预发布版 MultiValueDictionary(您可以通过 NuGet 获得)。

        这种方法产生 O(1) 查找:

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

        【讨论】:

          猜你喜欢
          • 2015-09-05
          • 1970-01-01
          • 1970-01-01
          • 2022-12-07
          • 1970-01-01
          • 2022-07-12
          • 1970-01-01
          • 1970-01-01
          • 2017-07-27
          相关资源
          最近更新 更多