【问题标题】:Convert List of names to Dictionary, where each entry corresponds to names that begin with a certain letter将名称列表转换为字典,其中每个条目对应于以某个字母开头的名称
【发布时间】:2014-11-19 13:38:31
【问题描述】:

我创建了一些返回 Dictionary<string, List<Employee>> 的方法,在此方法中我循环遍历 List<Employee> 并查找名字并将其按字母顺序添加到我的字典中

看下面的例子:

  • 员工
    • 艾克,乔迪
    • Doe,约翰
    • Doe,简
    • 等。

其中第一部分是姓氏,第二部分是名字

我的方法创建一个这样的字典

  • “D”,列表({Doe, John}, {Doe, Jane})
  • “E”,列表 ({Eijk, Jordy})

方法:

public async Task<Dictionary<string, List<Employee>>> GetAllOrderdedByNameAsync()
    {
        var dbList = await _employeeRepository.ListAsync();
        var employees = dbList.Select(FromDb).ToList();
        var empDict = new Dictionary<string, List<Employee>>();
        for (char c = 'A'; c <= 'Z'; c++)
        {
            var list = employees.Where(employee => employee.LastName.StartsWith(c.ToString(), StringComparison.CurrentCultureIgnoreCase)).ToList();
            if (list.Count > 0)
            {
                empDict.Add(c.ToString(), list);
            }
        }
        return empDict;
    }

现在我的问题...有没有更好的方法来做到这一点?我将保留List&lt;Employee&gt; 作为输入并需要Dictionary&lt;string,List&lt;Employee&gt;&gt; 作为输出,所以请不要说我需要返回其他内容。

【问题讨论】:

    标签: c# list dictionary


    【解决方案1】:

    听起来你真的想要一个ILookup&lt;string, Employee&gt;,它恰好是一个字典,其中每个键都映射到可能的多个值。是的,您可以创建Dictionary&lt;string, List&lt;Employee&gt;&gt;,但我强烈建议您不要这样做。你说你“需要”Dictionary&lt;string,List&lt;Employee&gt;&gt; - 为什么?

    查找代码为:

    var lookup = list.ToLookup(x => x.Substring(x.LastName(0, 1)),
                               StringComparer.CurrentCultureIgnoreCase);
    

    要获取字典,如果你真的有充分的理由,你可以使用:

    var dictionary = list.GroupBy(x => x.Substring(x.LastName(0, 1)))
                         .ToDictionary(g => g.Key, g => g.ToList(), 
                                       StringComparer.CurrentCultureIgnoreCase);
    

    ...但正如我所说,我会强烈建议使用已经准确表示您正在寻找的类型,以更简洁的方式。 (它还有一个很好的特性是允许你按任意键查找,如果没有条目则返回一个空序列。)

    您可能还想考虑使用 char 作为您的密钥,而不是 string,因为您只处理单个字符 - 并且还要考虑您希望对姓氏发生什么,例如“de Havilland” " 或以重音字符开头的字符。 (换句话说,您可能想要执行一些规范化。)

    【讨论】:

    • 哇,你打字这么快,在LastName 上使用SubstringFirst 有优势吗(这是我对你的回答的唯一区别)
    • @sa_ddam213:好吧,First 将返回 char 而不是 string.... 那时您不妨使用 [0]
    • 啊,没关系,charstring 会是我猜的答案 :)
    • 您好乔恩,感谢您的回答。但是有一个问题。我真的需要一份员工名单。我将它用于 GridView (StoreApp) 与分组的 CollectionViewSource
    • @Jordy:如果你需要一个列表,你为什么要字典?如果您需要每个条目的列表,您可以随时在需要时从查找中调用每个项目的 ToList。
    【解决方案2】:

    我很抱歉不相信你;)

    它确实像它应该做的那样工作。在查找ILookup on MSDN 之后,仍然有点不清楚它是如何工作的。但我设法实现了它。

    这里有一些示例代码,供所有想知道我是如何做到的人的。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace ConsoleSandbox
    {
    class Program
    {
        static void Main(string[] args)
        {
            var vm = new ViewModel();
    
            var lookupEmployees = vm.GetAllOrderedByName();
    
            foreach (var group in lookupEmployees)
            {
                Console.WriteLine(group.Key);
                foreach (var employee in group)
                {
                    Console.WriteLine("\t"+employee);
                }
            }
            Console.Read();
        }
    }
    
    public class ViewModel
    {
        public ViewModel()
        {
            //Fill Employees
            Employees = new List<Employee>
            {
                new Employee{ FirstName = "Jordy", LastName = "Eijk van"},
                new Employee{ FirstName = "Jon", LastName = "Skeet"},
                new Employee{ FirstName = "John", LastName = "Doe"},
                new Employee{ FirstName = "Jane", LastName = "Doe"},
                new Employee{ FirstName = "Jack", LastName = "Ripper the"}
            };
        }
    
        public List<Employee> Employees { get; set; }
    
        /// <summary>
        /// Get the Employees by name
        /// </summary>
        /// <returns></returns>
        public ILookup<string, Employee> GetAllOrderedByName()
        {
            return Employees
                .OrderBy(e=>e.LastName)
                .ThenBy(e=>e.FirstName)
                .ToLookup(e => e.LastName.Substring(0, 1), StringComparer.CurrentCultureIgnoreCase);
        }
    }
    
    public class Employee
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    
        public override string ToString()
        {
            return string.Format("{0} {1}", LastName, FirstName);
        }
    }
    }
    

    它是一个简单的控制台应用程序

    【讨论】:

      猜你喜欢
      • 2012-04-25
      • 1970-01-01
      • 2021-02-15
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      • 2010-09-05
      • 1970-01-01
      • 2016-08-27
      相关资源
      最近更新 更多