C# and Fox versions of Cool Linq Query

In my prior post (Cool Linq Query) I promised a C# and Fox versions of a query to sort all the “Words” found in many files in a C++ project and sort them by frequency of occurrence.

The C# version: it’s almost the same as the VB version. Try typing it out and you’ll see differences in Intellisense between C# and VB

Just start VS2008, choose File->New->Project->C#->Windows Forms Application, View Code, then paste in the C# code below

Note how the TakeWhile is called as an extension method, rather than as a query clause.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.IO;

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)

        {

            this.Width = 1024;

            this.Height = 768;

            var q =

                from FileName in Directory.GetFiles(

                  "D:\\dd\\VB03_s2\\src\\vb\\bc\\", "*.*",

                  SearchOption.AllDirectories)

  let ext = Path.GetExtension(FileName).ToLower()

                where ext == ".cpp" || ext == ".h"

                let LineArray = File.ReadAllText(FileName).Split(new char[] { '\n', '\r' })

                from SingleLine in LineArray

     let WordArray = SingleLine.Split(

                           new char[] { ' ', '\t', '*', ',', '.', '(', ')', '<', '>', ':',';', '\'', '"' }

                       ).TakeWhile(w => w != "//")

                from word in WordArray

              where word.Length > 0 && System.Char.IsLetter(word[0])

                group word by word into gr

                orderby gr.Count() descending

                select new { dd = gr.Count(),gr.Key};

            Browse(q);

        }

        private void Browse<T>(IEnumerable<T> seq)

        {

            var Gridview = new DataGridView();

            Gridview.Width = this.Width;

            Gridview.Height = this.Height;

            this.Controls.Add(Gridview);

            var p1 = new List<T>(seq);

     Gridview.DataSource = p1;

            this.Text = p1.Count.ToString();

            Gridview.Dock = DockStyle.Fill;

            Gridview.AutoResizeColumns();

        }

    }

}

End of C# code

This Fox version uses GETWORDCOUNT() and GETWORDNUM() in a loop, which means the beginning of the line is parsed N times for N words in the line.

xx=CREATEOBJECT("QueryFiles")

DEFINE CLASS QueryFiles as Form

      PROCEDURE init

            CREATE CURSOR words (word c(100))

            CREATE CURSOR files (filename c(240),depth i)

            cDelim="[]; @*,.()<>,:;*"+CHR(34)

            this.DoDir("D:\dd\VB03_s2\src\vb\bc\")

            SCAN && for each file

                  IF .t.

                        CREATE CURSOR FileText (cLine c(250)) && alternatively, could use FILETOSTR(), ALINES()

                        APPEND FROM (files.filename) sdf && get the file contents into a cursor

                        SCAN && for each line in file

                              n=GETWORDCOUNT(cLine,cDelim)

                              FOR i = 1 TO n

                                    cWord=GETWORDNUM(cLine,i,cDelim)

                                    IF ISALPHA(cWord)

                                          INSERT INTO words VALUES (cWord)

                                    ENDIF

                              ENDFOR

                        ENDSCAN

                  ELSE

                        nLines=ALINES(arrLines,FILETOSTR(files.filename))

                        FOR j = 1 TO nLines

                              cLine=arrLines[j]

                              n=GETWORDCOUNT(cLine,cDelim)

                              FOR i = 1 TO n

                                    cWord=GETWORDNUM(cLine,i,cDelim)

                                    IF ISALPHA(cWord)

                                          INSERT INTO words VALUES (cWord)

                                    ENDIF

                              ENDFOR

                        ENDFOR

                       

                  ENDIF

            ENDSCAN

            SELECT word,COUNT(*) FROM words GROUP BY 1 ORDER BY 2 DESC INTO CURSOR result

            this.Visible=1

            this.Width=1024

            this.Height=768

            this.AddObject("grd","Grid")

            WITH this.grd as Grid

                  .Width=this.Width

                  .Height=this.Height

                  .Anchor=15

                  .Visible=1

            ENDWITH

      PROCEDURE DoDir(cPath as String) as Number && Recursive routine to get folders and their sizes

            LOCAL n,i,aa[1],nTotal,nFileTotal

            nTotal=0

            nFileTotal=0

            n=ADIR(aa,cPath+"*.*","D")

            FOR i = 1 TO n

                  IF "D"$aa[i,5]

                        IF aa[i,1] != '.'

                              this.DoDir(cPath+aa[i,1]+"\")

                        ENDIF

                  ELSE

                  IF INLIST(JUSTEXT(aa[i,1]),"CPP","H")

                              INSERT INTO files VALUES (cPath+aa[i,1],0)

                        ENDIF

                  ENDIF

            ENDFOR

           

ENDDEFINE

End of fox code