Tuesday 9 February 2010

Some useful methods

The other day I found myself with such a simple task as turning a long list of tab separated rows into a html table. In these times of Linq, functional programming, declarative programming... it seems like normal loops are no longer fun, so I came up with this solution:



   1:  string lineFormat = "<tr>\n" +

   2:                              "<td>{0}</td>\n" +

   3:                              "<td>{1}</td>\n" +

   4:                              "<td>{2}</td>\n" +

   5:                              "<td>{2}</td>\n" +

   6:                              "</tr>\n";

   7:  result = String.Join("", txt.Split("\n".ToCharArray())

   8:                          .Select(line => String.Format(lineFormat,line.Split("\t".ToCharArray())))

   9:                          .ToArray());



Looking at that code, there's something that hurts a bit, those 4 <td>n</td> lines, product of copy pasting... so, thinking of a nicer way to create that string of html:



   1:  string template = "<td>{{{0}}}</td>\n";

   2:  String.Join("", 

   3:       Enumerable.Range(0,4)

   4:       .Select(num => String.Format(template,num)).ToArray());



Wow, sure at first sight is rather less clear than the initial "hardcoded" version, but this one is cooler :-)

In both codeblocks above I'm using the String.Join method. That's OK, but first I don't like the fact that it needs and array instead of just an IEnumerable<string> and second, it breaks a bit the "fluent style" that I like so much, so after some fast investigation I found it can be replaced with Enumerable.Aggregate, so the last line would look like this:



   1:  res = 

   2:          Enumerable.Range(0,4)

   3:                   .Select(num => String.Format(template,num))

   4:                   .Aggregate((it1, it2) => it1 + it2);



This coding with the String.Format and Collections made me recall an Extension method that I coded some time ago:



   1:  /// <summary>

   2:          /// Does a looped String.Format, that is, apply the formatting pattern to an enumeration of elements and joins the results

   3:          /// </summary>

   4:          /// <typeparam name="T">Type of the item that will be formatted with the pattern</typeparam>

   5:          /// <param name="pattern">string pattern</param>

   6:          /// <param name="enumerable">enumeration of items to be formatted</param>

   7:          /// <param name="joiner"></param>

   8:          /// <param name="selectors">array of methods that select from the item the values to be used in the formatting</param>

   9:          /// <returns></returns>

  10:          public static string FormatEach<T>(this string pattern, IEnumerable<T> enumerable, string joiner, params Func<T, string>[] selectors)

  11:          {

  12:              //rather interesting, I'm using 2 nested Selects, that's equivalent to using 2 nested loops.

  13:   

  14:              return String.Join(joiner,

  15:                                 enumerable.Select(item => string.Format(

  16:                                                                              pattern,

  17:                                                                              selectors.Select(selector => selector(item)).ToArray()

  18:                                                                         )

  19:                                                   ).ToArray());

  20:  }



It applies a format string to a collection of objects and joins together the resulting strings. The formatting of each element in the collection differs from the normal String.Format in that instead of using an Array of objects I use an object from which I extract the values to use in the formatting through the application of the corresponding projection delegate in the selectors array.

Extension methods have been an incredibly useful addition to .Net, and one sometimes wonders, why didn't they add more?
For example, it's rather annoying not being able to do this:

string sr = "a"*5;

OK, in 2002, when .Net was released and it looked like a much more "traditional" platform, maybe it wasn't an operation in everyone's mind, but now that almost everyone has got used to the expressive wonders of languages like Python, Javascript (yes, I know, you can't do that in JS, but anyway) it seems like a rather reasonable addition.
So, just add an expression method and we're done...
Wait, not so easy, unfortunately you can't have operator overloads in a Static Class... but well, at least it would be rather convenient to have a method like this:

string sr = "a".Multiply(5);

I've added one to NAsturLib, my small library of convenience methods, code reminders and non particularly useful code attempts...



   1:  public static string Multiply(this string s, int times)

   2:          {

   3:                return Enumerable.Range(1, times)

   4:                      .Select(num => s)

   5:                      .Aggregate((cur, next)=> cur + next);

   6:              

   7:          }



Well, time to close this "mosaic of damn easy methods that I want to have easily accessible for future reuse" post (yes, I'm afraid my blog will end up turning into sort of a personal Pastebin...)

No comments:

Post a Comment