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