Monday, January 25, 2010

Tokenizer / tag extraction method

I was in need for a method to extract a list of tokens from a given text.
The list should not contain stopwords like "the, a, on, of, etc" or punctuation marks and needs to be sorted by most used token.
This is what i came up with:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public static class Tokenizer
{
private class Token
{
public string Value { get; set; }
public int Count { get; set; }
}

/// <summary>
/// Tokenize a string and return tokens as list sorted by most occurances
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static List<string> TokenizeString(string input)
{
string cleanText = String.Empty;

// Replace all non-alphanumeric characters with a space
new List<Char>(input.ToCharArray()).ForEach(c =>
cleanText += (Char.IsLetterOrDigit(c) || Char.IsWhiteSpace(c))
? c.ToString()
: " ");

// We want all tokens in lowercase
cleanText = cleanText.ToLower();

// Split input string on whitespaces
List<string> tokens = cleanText.Split(' ').ToList<string>();

// Remove stop words, whitespace and tokens shorter than 3 chars from token list
// NOTE: Configuration.StopWords is of type List<string> and contains the stopwords (loaded from a configuration file)
Configuration.StopWords.ForEach(stopWord =>
tokens.RemoveAll(token =>
token == stopWord || String.IsNullOrWhiteSpace(token) || token.Length < 3));

// Copy the tokens to a new list
// Count how many times each token occurs and add it only once, so we have no double entries
List<Token> tokenList = new List<Token>();
tokens.ForEach(delegate(string t)
{
// Continue only if token does not exist in tokenList
if (!tokenList.Exists(e => e.Value == t))
{
// Add token to list, including the count of how many times it occurred
tokenList.Add(new Token { Value = t, Count = tokens.Count<string>(c => c == t) });
}
});

// Sort the list on occurrance count
tokenList.Sort(delegate(Token a, Token b)
{
return b.Count.CompareTo(a.Count);
});

// At this point we have a list with unique tokens, sorted by most occurrances
// We convert it back to a string list and return it
tokens = new List<string>();
tokenList.ForEach(t => tokens.Add(t.Value));

return tokens;
}
}

Here is an example of it's usage:

// Dummy input string
string input = "Google-oprichters Larry Page en Sergey Brin willen af van hun gedeelde meerderheid aan aandelen van het bedrijf. Uit een bericht van de Amerikaanse beurswaakhond SEC willen de twee de komende vijf jaar tien miljoen van hun Google aandelen verkopen. Brin en Page, nu nog voor 59 procent eigenaar, bezitten dan nog maar 48 procent van de aandelen. Met de huidige koers levert dat hun in totaal 5,5 miljard euro op. De Google oprichters kiezen bewust voor een geleidelijke afbouw om de aandelen op de beurs niet teveel onder de druk te zetten. Ondanks de aandelenverkoop zullen Brin en Page nog aardig hun stempel op het beleid kunnen drukken. Naast henzelf zijn voor besluiten slechts krap twee procent van de overige aandeelhouders nodig.";

List<string> tokens = Tokenizer.TokenizeString(input);

This will result in 59 tokens with the first 5 being:

aandelen
google
brin
nog
procent


The list of stopwords that was loaded in Configuration.StopWords is: aan,naar,dat,nu,de,om,den,onder,der,ons,des,onze,deze,ook,die,op,dit,over,door,een,te,enige,tegen,enkele,ten,enz,ter,etc,tot,haar,uit,het,hierin,hoe,vanaf,hun,ik,vol,inzake,voor,is,wat,je,wie,na,zijn,u,uw,met,naar,jij,hij,zij,zonder,en,van,amp

Because i already had a list with dutch stopwords loaded, i have used a dutch text in the example (sorry english readers :)

/Ruud

Wednesday, December 16, 2009

C# Coding Standards

I have always been very keen on coding standards and as believe that a strict standard is key to writing maintainable code.
Today i stumbled upon a document that summarizes all the C# coding standards that i usually apply.
Thanks to Lance Hunt for publishing this document!

Get the document here: http://weblogs.asp.net/lhunt/pages/CSharp-Coding-Standards-document.aspx

/Ruud

Tuesday, November 3, 2009

Learn ASP.NET MVC in 2 hours! An introduction to MVC.NET

There is a new sheriff in town and it's called ASP.NET MVC!
This (fairly) new framework from Microsoft provides the possiblity to write applications that truely follow the MVC design pattern which allows clear separation of data, logic and user interface.
That strict seperation results in better testibility and maintanability.
I was very excited about this framework from the start, but didn't get into the details until now and i found that - once again - a blog series from ScottGu is a very good start for those who want to learn to use ASP.NET MVC.

So here we go: learn MVC.NET in 2 hours (depending on how fast you read of course)!

Part 1: ASP.NET MVC Framework
http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx

Part 2: URL Routing
http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx

Part 3: Passing ViewData from Controllers to Views
http://weblogs.asp.net/scottgu/archive/2007/12/06/asp-net-mvc-framework-part-3-passing-viewdata-from-controllers-to-views.aspx

Part 4: Handling Form Edit and Post Scenarios
http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx

Thank you Scott!

And for those who can't get enough, there is more!
The latest version - ASP.NET MVC 2.0 - is now available as preview and Brad Wilson wrote a blog series about one of the major new features in this release: Templates.

Part 1: Introduction
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html

Part 2: ModelMetadata
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html

Part 3: Default Templates
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html

Part 4: Custom Object Templates
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html

Part 5: Master Page Templates
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html

Thank you Brad!

/Ruud

Thursday, October 22, 2009

.NET trace log implementation with EventLog and TextStream support

When you are developing an application you want to be able to log what is happening in your code.
In .NET you can accomplish that with the use of TraceListeners.
You use the Trace class to write messages during the execution of your application.
While in debug mode, these messages will be displayed in the Visual Studio output console and forwarded to the configured tracelisteners.
The TraceListener can then write the message to a destination like an EventLog, Xml file or a textfile.
One cool thing about TraceListeners is that you can configure them in your App.config or Web.config, so you can control their settings after you have built the application.

I think this is a great tool for implementing logging in your application, but the default implementation has a few setbacks:

1) TraceListeners intercept all trace messages and i would like to configure them so they intercept only those messages that have a specific priority level.
Eg. i want high priority messages to be logged in an eventlog and i want debug messages to be logged in a textfile.
So when i use a release build and something goes wrong, i can activate the TraceListener that writes debug info to a logfile and find out what is happening.

2) The EventLogTraceListener outputs to the Application log and i would like to have my events in a seperate log.

So to solve these problems i wrote my own tracelisteners.
It would be great if Microsoft was so kind to let us inherit from their default tracelistener implementations like EventLogTraceListener and TextStreamTraceListener, but for some reason they decided to seal these classes.
Therefore we have to inherit from the TraceListener class, do our custom stuff and pass the calls to an instance of, for example, EventLogTraceListener.
I wrote two custom tracelisteners: CustomEventLogTraceListener and CustomTextStreamTraceListener.

In my implementation i also wrote a CustomTrace class that acts as a wrapper for the Trace class and adds the possibility of specifying priority levels for trace messages.
The lowest priority is 1 and the highest is 9.
So instead of calling Trace.TraceError("This is wrong") you can call CustomTrace.TraceError("This is wrong", 9) which means this error is of priority level 9, so it is very important.

I created an example solution with the TraceListeners project and an example application.
It shows how to configure the listeners and how to send information (messages) to them.

I will be using this in all my .NET implementations from now on and i hope it comes in handy for you too!

/Ruud

Wednesday, October 21, 2009

Maintenance

Downloads and code highlighting component are temporarily disabled.
They are all hosted on the DotTech domain which is offline for maintenance.
I try to have them back online this weekend.

EDIT: Server is back up!

/Ruud

Tuesday, October 13, 2009

ScottGu's VS2010 and .NET 4 Series

I'd like to point out a nice series of blogposts from Scott Guthrie on Visual Studio 2010 and .NET 4.0
For those of you who don't know Scott Gu (you are a rare breed): he runs the development teams for ASP.NET, CLR, IIS7, Windows Presentation Foundation and some other MS projects.

His blog series about VS2010 and .NET 4.0 is good reading material for those who want to be somewhat prepared when the software is released.

I will update this post when he publishes more articles.
Enjoy!

/Ruud

Tuesday, September 15, 2009

Announcing SharePaste.com

I often found myself in the situation where i quickly want to save whatever is on my clipboard, for example while i'm working on some code and want to remove a section but might need it later.
Sometimes i want to share whatever is on my clipboard, when i want feedback on it or when i want to send someone some code to help him out.

Now, i thought it would be handy to have an online tool for this so that i can quickly paste some text, save it and access it by a short URL so that i can share it with others.
For this reason i created SharePaste, the easy way to save and share your clipboard contents.

SharePaste.com

It provides you with a straight forward interface that allows you to paste and save your text within seconds.
There is support for syntax highlighting and in the future you have the ability to register yourself to keep track of previous pastes.
The tool is still in early beta and registration is not available yet, but it's already very usefull.

Here is a short overview of SharePaste's features:
- Save any text that is on your clipboard
- Share your pastes using their unique, short URL
- Access your saved pastes any time
- Apply syntax highlighting to your pastes
- Find your pastes back by searching on their tags (not yet implemented)
- More features are coming!

And here is one example of what a paste looks like: http://sharepaste.com/p/giD3B7.

I hope you like it and find it as usefull as i do!

/Ruud