zoukankan      html  css  js  c++  java
  • C#Linq转换运算符ToDictionary, ToLookup

    C#探秘系列(一)——ToDictionary,ToLookup

     更新时间:2014年05月14日 08:49:25   作者:    我要评论

    这个系列我们看看C#中有哪些我们知道,但是又不知道怎么用,又或者懒得去了解的东西,比如这篇我们要介绍的toDictionary和ToLookup。

    这个系列我们看看C#中有哪些我们知道,但是又不知道怎么用,又或者懒得去了解的东西,比如这篇我们要介绍的toDictionary和ToLookup。

      从图中我们看到有四个ToXXX的方法,其中ToArray和ToList,我想大家用的是非常非常多,但是ToDictionary和ToLookup不见得有多少人用了,但不能否认的是这些方法确实很有用。

         不多废话了,直接如主题,我们有这样的一个实体,包含:票号,订单号,备注。
    class Ticket {
            /// <summary>
            /// 票号
            /// </summary>
            public string TicketNo { get; set; }

            /// <summary>
            /// 订单号
            /// </summary>
            public int OrderID { get; set; }

            /// <summary>
            /// 备注
            /// </summary>
            public string Description { get; set; }
        }

    好了,我们看看需求,票号和订单号是一对多的关系,也就是说一个订单号可能包含几个票号,每个票号都有自己对应的状态,比如票号有 “改签”,"未使用",“成交”,"退票" 等等,下面我们灌一批数据进去。


    public static List<Ticket> GetList()
            {
                return new List<Ticket>()
                {
                     new Ticket(){ TicketNo="999-12311",OrderID=79121281,Description="改签"},
                     new Ticket(){ TicketNo="999-24572",OrderID=29321289,Description="退票"},
                     new Ticket(){ TicketNo="999-68904",OrderID=19321289,Description="成交"},
                     new Ticket(){ TicketNo="999-24172",OrderID=64321212,Description="未使用"},
                     new Ticket(){ TicketNo="999-24579",OrderID=19321289,Description="退票"},
                     new Ticket(){ TicketNo="999-21522",OrderID=79121281,Description="未使用"},
                     new Ticket(){ TicketNo="999-24902",OrderID=79121281,Description="退票"},
                     new Ticket(){ TicketNo="999-04571",OrderID=29321289,Description="改签"},
                     new Ticket(){ TicketNo="999-23572",OrderID=96576289,Description="改签"},
                     new Ticket(){ TicketNo="999-24971",OrderID=99321289,Description="成交"}
                };
            }

    举个例子: 我需要统计各个订单号中的票号情况。

          很明显,这是一个分组排序的问题,可能你马上就想起了groupby来实现,当然groupby是可以实现的,不过groupby不能算是一种数据

    结构,不能带有索引,没有字典那样容易输出和操作。

    方案一: 采用普通的foreach循环。

                 一般情况下,可能有一部分人都采用这种原始的方法,将list数据通过foreach循环放到dictionary中,就是代码写的多一些,也算

    是最灵活的。


    Dictionary<int, Ticket> dic = new Dictionary<int, Ticket>();

                foreach (var item in ticketlist)
                {
                    if (!dic.ContainsKey(item.OrderID))
                    {
                        dic.Add(item.OrderID, item);
                    }
                    else
                    {
                        dic[item.OrderID] = item;
                    }
                }

    方案二:使用ToDictionary

           从图中我们可以看到,发生悲剧的异常了,我们知道dictionary中key是不能重复的,然而ToDictionary中并没有给我们做key的重复值判断,那也就侧面说明ToDictionary在kv中只能是 “一对一”的关系,也就是v中永远只会有一条记录,显然这不是我需要的,在了解ToDictionary原理后,该方案失败。

    方案三: 使用ToLookup

      也许微软知道客户有这么个需求,就采用了一个ToDictionary的加强版,你也可以认为是一种新的字典数据结构,它就避免了这种“一对一”的关系,采用“一对多”的实现。


    var dic = ticketlist.ToLookup(i => i.OrderID);

                foreach (var item in dic)
                {
                    Console.WriteLine("订单号:" + item.Key);

                    foreach (var item1 in item)
                    {
                        Console.WriteLine("\t\t" + item1.TicketNo + "  " + item1.Description);
                    }
                }

    而且ToLookup和字典一样,是带有索引形式,这个groupby就不具备了,当然Tolookup还有一个强大的功能,就是使用Func<TSource, TElement> elementSelector来对现在的v元素进行转换来避免我刚才  Console.WriteLine("\t\t" + item1.TicketNo + "  " + item1.Description);语句

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ToDictionaryDemo
    {
        class Program
        {
            public class Game
            {
                public string Opponent { get; set; }
                public string Score { get; set; }
            }
            static void Main(string[] args)
            {
                var spartans = new List<Game>
                {
                    new Game{Opponent="UAB",Score="55-18"},
                    new Game{Opponent="Bowling Green",Score="55-18"},
                    new Game{Opponent="Pittsburgh",Score="55-18"},
                    new Game{Opponent="Notre Dame",Score="55-18"}
                };
                //字典是一种键值对的集合,ToDictionary 将一个IEnumerable<T>对象(比如LINQ查询所返回的结果)
                //转换为一个IDictionary<Key,Value>对象。
                IDictionary<string, Game> stats = spartans.ToDictionary(key => key.Opponent);
                Console.WriteLine("Spartans vs. {0} {1}", stats["Notre Dame"].Opponent, stats["Notre Dame"].Score);
                Console.ReadLine();
            }
        }
    }
  • 相关阅读:
    LeetCode 230. 二叉搜索树中第K小的元素(Kth Smallest Element in a BST)
    LeetCode 216. 组合总和 III(Combination Sum III)
    LeetCode 179. 最大数(Largest Number)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 106. 从中序与后序遍历序列构造二叉树(Construct Binary Tree from Inorder and Postorder Traversal)
    指针变量、普通变量、内存和地址的全面对比
    MiZ702学习笔记8——让MiZ702变身PC的方法
    你可能不知道的,定义,声明,初始化
    原创zynq文章整理(MiZ702教程+例程)
  • 原文地址:https://www.cnblogs.com/grj001/p/12225096.html
Copyright © 2011-2022 走看看