那天有个小孩跟我说LINQ(三)

来源:互联网 发布:java中构造方法的定义 编辑:程序博客网 时间:2024/05/01 03:13

小孩LINQ系列导航:(一)(二)(三)(四)(五)(六)(七)

1  LINQ TO Objects续2(代码下载)

     新建项目 linq_Ch3控制台程序

       image

       1.1 操作字符串

       ①查找字符串中包含的大写字母,字符串是由多个char类型组成

            //1.查找字符串中包含的大写字母
            string string1 = "int I=10;string String1=(I%2==0?\"偶数\":\"奇数\")";
            //过滤字符换中所有的大写字母,判断小写用IsLetter,数字用IsDigit,标点用IsPunctuation,控制字符用IsControl,分隔符用 IsSeparator,符号类型用
            //IsSymbol,例如“=”,空白类型字符用IsWhiteSpace
            var query = from s in string1
                        where char.IsUpper(s)
                        select s;
            Console.WriteLine("大写字母有:");
            foreach (var item in query)
            {
                Console.Write(item.ToString()+"\t");
            }
    效果图:

           image

 

       ②查找字符串中包含数字,用char.IsDigit(char类型的),写法同上

      ③查找字符串中标点符号,用char.IsPunctuation(char类型的),写法同上

      ④过滤文章中包含指定单词的句子(学习let

          let子句

          在查询表达式中,存储子表达式的结果有时很有用,这样可以在随后的子句中使用。可以使用let关键字完成这一工作,该关键字可以创建一个新的范围变量,并且用提供的表达式的结果初始化该变量。一旦用值初始化了该范围的变量,他就不能用于存储其他值。如果该范围变量存储的是可查询的类型,则可以对齐进行查询

代码如下:

  Console.WriteLine();
            //2.过滤文章指定的单词
            string text = "While taking my boat down the inland waterway to Florida a few weeks ago, I decided to tie up at Georgetown, South Carolina, for the night and visit with an old friend. As we approached the Esso dock, I saw him through my binoculars standing there awaiting us. Tall and straight as an arrow he stood, facing a cold, penetrating wind—truly a picture of a sturdy man, even though his next birthday will make him eighty-two. Yes, the man was our elder statesman, Bernard Baruch.  He loaded us into his station wagon and we were off to his famous Hobcaw Barony for dinner. We sat and talked in the great living room where many notables and statesmen, including Roosevelt and Churchill, have sat and taken their cues. In his eighty-second year, still a human dynamo, Mr. Baruch talks not of the past but of present problems and the future, deploring our ignorance of history, economics, and psychology. His only reference to the past was to tell me, with a wonderful sparkle in his eye, that he was only able to get eight quail out of the ten shots the day before. What is the secret of this great man’s value to the world at eighty-one? The answer is his insatiable desire to keep being productive.  Two of the hardest things to accomplish in this world are to acquire wealth by honest effort and, having gained it, to learn how to use it properly. Recently I walked into the locker room of a rather well-known golf club after finishing a round. It was in the late afternoon and most of the members had left for their homes. But a half-dozen or so men past middle age were still seated at tables talking aimlessly and drinking more than was good for them. These same men can be found there day after day and, strangely enough, each one of these men had been a man of affairs and wealth, successful in business and respected in the community. If material  prosperity were the chief requisite for happiness, then each one should have been happy. Yet, it seemed to me, something very important was missing, else there would not have been the constant effort to escape the realities of life through Scotch and soda. They knew, each one of them, that their productivity had ceased. When a fruit tree ceases to bear its fruit, it is dying. And it is even so with man.  What is the answer to a long and happy existence in this world of ours? I think I found it long ago in a passage from the book, Genesis, which caught my eyes while I was thumbing through my Bible. The words were few, but they became indelibly impressed on my mind: “In the sweat of thy face shalt thou eat thy bread.”  To me, that has been a challenge from my earliest recollections. In fact, the battle of life, of existence, is a challenge to everyone. The immortal words of St. Paul, too, have been and always will be a great inspiration to me. At the end of the road I want to be able to feel that I have fought a good fight, I have finished the course, I have kept the faith.";
            string matches = "to"; //要查询的单词
            string[] sentences = text.Split(new char[]{'.','?','!',','}); //按句子转换成数组
            var query2=from item in sentences
                       let words=item.Split(new char[]{'.','?','!',';',':',',',' '},StringSplitOptions.RemoveEmptyEntries)//将句子按单词转换成数组
                       where words.Contains(matches)
                       select item;
            Console.WriteLine("含有"+matches+"的句子是:");
            foreach (var item in query2)
            {
                Console.WriteLine(item.ToString());
            }

效果图:

          image

 

    ⑤统计每个单词在一个字符串中出现的次数(使用Distinct()去掉重复的)

       原理:将字符串转成数组A,在使用Distinct()方法获得数组A的去重版本数组B

                 然后创建一个数组C存储数量,长度肯定是数组B的长度,这样数组B和数组C的长度一样,正好一个单词,对应一个数量,方便以后输出结果

                 遍历整个数组B,获得临时单词,以这个临时值作为条件用linq在数组A中找这个单词

                 然后找到后,在循环中用数组C保存找到的符合的同一个单词的出现的频率

                 以达到数组B和数组C一一对应,方便以后输出的效果

    Console.WriteLine();
            //2.过滤文章指定的单词
            string text2 = "While taking my boat down the inland waterway to Florida a few weeks ago, I decided to tie up at Georgetown";
            //拆分成以每一个单词为一个元素的字符串数组
            string[] allWords = text2.Split(new char[] { '.', '?', '!', ';', ':', ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
            //去掉单词数组中重复的单词,用Distinct()方法
            string[] distinctWords = allWords.Distinct().ToArray();
            //创建一个存放词频统计信息的数组,以不重复的单词的数量为长度
            int[] counts = new int[distinctWords.Length];
            //遍历每一个单词,每次以这个单词在allWords数组中查找,因为allWords没有去掉重复的
            for (int i = 0; i < distinctWords.Length; i++)
            {
                string tempWord = distinctWords[i];//在不重复的单词数组中一个个获得
                var query3 = from item in allWords
                                     where item.ToLower() == tempWord.ToLower()
                                     select item;
                counts[i] = query3.Count();
            }
            //输出词频统计结果
            for (int i = 0; i < counts.Count(); i++)
            {
                Console.WriteLine(distinctWords[i]+"出现了"+counts[i]+"次");
            }

 

效果图:

           image

同样的遍历后对比思想,我们可以查找 中文在一个字符串中的个数,这次我们使用正则

            string text3 = "衷心感谢你们对茗洋芳竹的支持,博客地址:http://www.cnblogs.com/AaronYang,谢谢你们";
            int cnt = 0;
            Regex rgx = new Regex("^[\u4E00-\u9FA5]{0,}$");
            for (int i = 0; i < text3.Length; i++)
            {
                cnt = rgx.IsMatch(text3[i].ToString()) ? ++cnt : cnt;
            }
            Console.WriteLine("”" + text3 + "“中中文有" + cnt.ToString()+"个");

效果图:

image

 

那么同样,我们现在想在一篇文章中找ing结果的单词

还记得我们上篇中,在linq的条件中加一个自定义的方法,比较条件

例如:

   var query5=from item in words

                   where item.EndsWith("ing")

                   select item;

同理,我们也可声明个正则,假如我们声明一个

      Regex r=new Regex(@"ing\b");

      然后查询中

  var query5=from item in words

                   where r.Match(item).Success==true)

                   select item;

思考方式就在这里,也就是linq中找出的临时值,你可以用临时值的相关方法去判断,也可以用外面的方法,比如遍历的每一次返回都是一个对象,你想比较这个对象中某些属性是否符合条件,一,你可以在外面写个自定一个方法,二、你在对象中写个方法,每次判断对象.方法,其实方法还有很多,这里不说了

 

    ⑤将两个集合中的元素串联起来(集合1.concat(集合2))

   1:    int[] arr1 = { 0,1,2,3,4,5,6,7,8};
   2:              int[] arr2 = { 8, 6, 4, 3, 2, 1, 10 };
   3:              var arr3 = arr1.Concat(arr2);
   4:              Console.WriteLine("串联后:");
   5:              foreach (var item in arr3)
   6:              {
   7:                  Console.Write(item+",");
   8:              }

效果图,可说明,concat是不去重复的

image

方式二:

   使用Array类的CopyTo方法也可以实现

 Console.WriteLine();
            int[] arr4 = new int[arr2.Length + arr1.Length];
            arr1.CopyTo(arr4, 0);
            arr2.CopyTo(arr4,9);
            Console.WriteLine("arr4的结果:");
            foreach (var item in arr4)
            {
                Console.Write(item + ",");
            }

  效果图:

image 

讲解CopyTo,数组1.CopyTo(数组2,在数组2中,数组1中的值插入的在数组2中索引位置)

arr1.CopyTo(arr4, 0);  在arr4的索引0的位置上开始复制arr1中的数据,arr1中一共9个值,也就是占据了arr4的0-8的位置

arr2.CopyTo(arr4,9);   然后在arr4的索引9的位置上开始复制arr2中的数据

如果不是9是4的话,那么arr1在arr4的4开始(包括4)的位置到索引8的位置的值都被arr2替换了

 

 

     1.2 使用LINQ操作文件,说白了也是操作集合

        准备工作:我们在d盘建立一个LinqStudy的文件夹,然后在里面新建两个文件夹,linq1和linq2,然后我么在linq1中建立几个文件,linq.doc,linq.txt,博客园.doc,博客园.txt

image

然后我们赋值linq.txt和博客园.doc放到linq2中去,然后我们再在linq2文件下建立 linq学习.ppt

image

然后我们回到linq文件夹,在linq.txt中添加点文字,改变该文件的长度大小

image

           还是在这个解决方案里新建一个linq_ch4的控制台程序

        image  image

    1.2.1 取两个目录中的同名文件

         我们使用

         public FileInfo[] GetFiles(string searchPattern)这个方法获得文件

         例如,过滤d:\LinqStudy\linq1目录中所有扩展名为.txt的文件

         dir.GetFiles("*.txt");

         代码如下:

   1:       string dir1 = @"D:\LinqStudy\linq1";
   2:              string dir2 = @"D:\LinqStudy\linq2";
   3:              List<FileInfo> files1 = new List<FileInfo>();
   4:              List<FileInfo> files2 = new List<FileInfo>();
   5:              foreach (string file in Directory.GetFiles(dir1))
   6:              {
   7:                  files1.Add(new FileInfo(file));
   8:              }
   9:              foreach (string file in Directory.GetFiles(dir2))
  10:              {
  11:                  files2.Add(new FileInfo(file));
  12:              }
  13:              var query2 = from file1 in files1
  14:                                   join file2 in files2
  15:                                   on file1.Name equals file2.Name
  16:                                   orderby file1.Name
  17:                                   select file1;
  18:              foreach (var item in query2)
  19:              {
  20:                  Console.WriteLine(string.Format("{0}\t{1}",item.Name,item.Length));
  21:              }

效果图:

image

同样我们也可以在加个条件,除了文件名一样,文件长度也要一样,才是同一个文件

image

效果图:

image

竟然获得后,我们就可以进行删除,复制等等操作了

关于FileInfo对象还有  创建时间啊,最近访问日期啊等等,例如FileInfo对象.CreateTime

 

    1.2.2 查找指定名称的文件

        例如我们查找文件名中还有.NET的后缀名为doc类型的文件

        var query=from file in files

                           where file.Extension==”.doc” && file.Name.IndexOf(”.NET”)>-1

                           orderby file.Name

                           select file;

       我们也可以通过这个方法获得,*号是通配符,跟sql中的*在like语句中一样的

       FileInfo[] files=dir.GetFiles(”*.NET*.doc”)  

 

   1.2.3 查找大文件

        例如我们想在某一个文件夹下查找1个G以上的文件  

         var query=from file in files

                           where file.Length>1000000000

                           orderby file.Length

                           select file;

         当然你也可以指定一个文件的长度的范围值,文件夹也可以指定,无指定时,你可以递归整个磁盘,然后目录然后文件,就这样查询,获得后,你也可以先只记那个文件的文件目录,或文件名显示等等

   1.2.4 查找只读文件

           var query=from file in files

                           where (file.Attributes & FileAttributes.ReadOnly)!=0

 

                           select file;

  1.2.4 查找包含指定内容的文件

 
            Console.WriteLine();
            string findStr = "LinqStudy";
            Console.WriteLine("包含" + findStr + "文字的txt文件如下:");
            var query3 = from file in files1
                         where file.Extension == ".txt"
                         let content = File.ReadAllText(file.FullName, System.Text.Encoding.Default)
                         where content.Contains(findStr)
                         orderby file.Name
                         select file;
            foreach (var item in query3)
            {
                Console.WriteLine(string.Format("{0}\t{1}", item.Name, item.Length));
            }

效果图:

     image

原理也很简单,File.ReadAllText(文件路径,编码方式),可以获得txt文件中的文字,然后用let关键字,将内容临时存到content变量中

 

注意:在这个例子中,读取文件内容时,使用ReadAllText()方法将文件的内容一次性全部读取到内存,如果文件很大,那么久非常耗损系统资源,我们可以使用流的方式,每次只读取一行数据,然后逐行判断。

 

 

 

 


到此为止,linq to Objects已经讲完了

下次我们主要讲linq to SQL

今天清明节,有事情,估计这几天也没时间写了,还请原谅

上次LINQ第二篇,由于你们的支持,已经上了48小时排行榜,谢谢你们


原创粉丝点击