Saturday, October 11, 2008

I've moved

For those 3 people that have actually found this place, I moved to a new place. http://www.byatool.com

Friday, October 3, 2008

Fabulous Adventures in Reading

So on my new favoritest site ever for the week StackOverflow someone asked if this could be done in C#:
$patterns[0] = '/=C0/';
$patterns[1] = '/=E9/';
$patterns[2] = '/=C9/';


$replacements[0] = 'à';
$replacements[1] = 'é';
$replacements[2] = 'é';
return preg_replace($patterns, $replacements, $text);
I thought this could be an interesting challenge with Linq. And all things can be solved with Linq. Also, this post provides a valuable moral at the end.

So what the hell is that? Basically the idea is to take in some text, you know the stuff you send to people on your phone, and replace one set of characters with another. Make sense talk: TAKE TEXT! SMASH BAD THINGS! PUT GOOD THINGS IN!
String text;
List<Char> patternsToReplace;
List<Char> patternsToUse;

patternsToReplace = new List<Char>();
patternsToReplace.Add('a');
patternsToReplace.Add('c');
patternsToUse = new List<Char>();
patternsToUse.Add('X');
patternsToUse.Add('Z');

text = "This is a thing to replace stuff with";

var allAsAndCs = text.ToCharArray()
               .Select
               (
                 currentItem => patternsToReplace.Contains(currentItem)
                   ? patternsToUse[patternsToReplace.IndexOf(currentItem)]
                   : currentItem
               )
               .ToArray();
        
text = new String(allAsAndCs);
It's actually very simple. First convert the text into a character array. Then select through them one by one. If the list of ones to be replaced (patternsToReplace) just happens to have the current character, replace it with the corresponding one from the replacements (patternsToUse) otherwise just return the original.

Now the annoying thing about this example is that in preg_replace the two lists have no real correlation. It just assumes you want and index to index match. Therefore patternsToUse[0] replaces patternsToReplace[0]. But hey, I didn't invent the thing.

Another note is that instead of using Char[] I used List<Char> because arrays don't have index of and it saves the one step of charArray.ToList().IndexOf. I'm lazy and I like lists.

Now for the moral of the story:

'Course I dove right into Linq and responded... not reading that he/she needed a 2.0 solution and ultimately gave the client NOTHING THAT HE/SHE WANTED. So, if you take anything from this... and you probably won't... Always read the requirements first.

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

Wednesday, October 1, 2008

OrderBy using a Property Name

Now this is kind of dangerous to do since there is no compile time check (Like most things set in markup) but say you want to sort a collection, using the Linq extension methods, but you don't know what you what to sort on at any given time. On top of that, you have a datagrid and a bunch of sort expressions to deal with. Now you could do something like create a hashtable full of lambda expressions that the key is the sort expression:
Dictionary<String, Func<User, IComparable>> list;

userList = User.GetUserList();
list = new Dictionary<String, Func<User, IComparable>>();
list.Add("UserName", currentUser => currentUser.UserName);
list.Add("UserID", currentUser => currentUser.UserID);
userList.OrderBy(list["UserID"]);
Works just fine, and might be preferable to what I'm about to show. OooOoOO sound eerie?
//This is just to get the property info using reflection.  In order to get the value
//from a property dynamically, we need the property info from the class
public static PropertyInfo[] GetInfo<K>(K item) where K : class
{
  PropertyInfo[] propertyList;
  Type typeInfo;
        
  typeInfo = item.GetType();
  propertyList = typeInfo.GetProperties();
        
  return propertyList;
}

//This is the dynamic order by func that the OrderBy method needs to work
public static IComparable OrderByProperty<T>(String propertyName, T item)
  where T : class
{
  PropertyInfo[] propertyList;
        
  propertyList = GetInfo(item);

  //Here we get the value of that property of the passed in item and make sure
  //to type the object (Which is what GetValue returns) into an IComparable
  return (IComparable)propertyList.First(currentProperty
    => currentProperty.Name == propertyName).GetValue(item, null);
}
And use:
//This takes the current user and calls the OrderByProperty method which in turn
//gives us the Func OrderBy is requesting.
var test = userList.OrderBy(currentUser
  => DynamicPropertySort.OrderByProperty("UserID", currentUser)).ToList();
Ok so what the hell? I mean intellisense on the OrderBy method doesn't give much help. Func<<User, TKey>>. Yeah ok. So basically the return type is open. Well this kind of sucks right? Because I would have to return a Func that already knows the return type. (Be it string, int, ect) Of course, this would mean we would have to handle each sort expression in code. NOT VERY DYNAMIC IS IT? Well f that. Truth is, what the order by is looking for is a Func that takes in a User and returns something it can compare. This is where IComparable comes in. The OrderBy has to take the returned value, say UserID which is an int, and figure out how to compare it to another value. Pretty simple. So as long as the property you are ordering by uses IComparable, you're good to go. Pretty nice huh? Now I would suggest, if you use this (HAHAHAHA), is to cache a dictionary of the property info with the class type as the key so that you don't have to use as much reflection everytime. I just didn't put that in. U U USING

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