Killing the Fencepost in C#: A handy code snippet

A short while ago, a buddy was saying how learning Lisp had made him start thinking of everything in terms of map/reduce. As an example he gave me an example of a recent python snippet he’d written.

return reduce(lambda l, r: l + seperator + r, (str(s) for s in values))

While I’m not going to claim to be some sort of industry expert on the subject, and there are probably wikipedia entries and blog posts and Knuthian essays I haven’t read on the subject, this is pretty easily the most simple, elegant fencepost solution I’ve ever seen in my life. There are no special cases, boundary case handling, seeding (ie, initialize the final string to the first element, then start the loop at the second). It’s flexible, straightforward, relatively easy to understand to someone with a sufficient familiarity of lambdas. It just does its thing and disappears.

And then it occurred to me, since lambdas had been brought to c#, that this was suddenly within my power to accomplish as well.

I had certain goals in mind, as the snippet provided to me had set a serious benchmark. I wanted it to be as general and flexible as possible- It shouldn’t take only arrays, or only lists. You should be able to throw any sort of collection at it that you want. You also shouldn’t be restricted to only sending it Strings- Might as well make it possible to send it a collection of numbers, or people, or pretty much anything you want. This was more of a “hey, while we’re at it.” Feature creep, I know, I know. But it’s my exercise, and I’ll rock it as I see fit:D

Next, I wanted it to be as simple, elegant, and straightforward as possible. To me, the most significant thing about the snippet was, as stated above, that there was no special case code, and no seeding. You can develop an inferiority complex trying to make c# code as elegant as python code, because c# is a more verbose language. It just requires you to be much more explicit about everything than python does- Especially when it comes to LINQ and collections. Brackets, parentheses and curly braces everywhere. Still, I felt a degree of elegance was possible, and I was determined to find it. What can I say, I was bored, have had minimal exposure to functional programming, and the idea intrigued me…

Here’s what I came up with.

public static String fencepost(IEnumerable values, String seperator)
{
    IEnumerable<String> strings = values.Cast<Object>().Select(x => x.ToString());
    return strings.Aggregate((x, y) => x + seperator + y);
}

By way of explanation, LINQ is more an attempt at emulating SQL than functional programming. So the rough FP -> .NET corollaries are “Map” -> “Select”, “Reduce” -> “Aggregate”. Also, as a one liner it got way too complex to really be readable, so I split it up into two- The first line creates a typed Enumerable of type String from a typed or untyped collection, for the second line to work with.

I also somewhat bundled up the whole thing as a full method, which you can copy-paste somewhere and call whenever you need it, choosing your seperator token on the fly (comma, period, space, whatever). If, on the other hand, an in-line snippet is more your style, here’s a very straightforward one-liner (that assumes you have a typed collection)

  string seperator = ","; //Or whatever else you want to use
  string result = (String)foo.Aggregate((x, y) => x.ToString() + seperator + y.ToString());

Not quite as zen-like as the python version, but it has it’s own strongly-typed schwerve to it. I consider this “Garage Sale” code- Not really complicated enough to license it, so just copy/paste to your heart’s content. Enjoy:)

-Alex

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

Alex the first and third code snippets are empty.

Thanks for the heads-up- It was apparently only doing that in IE7, and I run firefox:P

Fixed now.

Thank you SO much for Migratr! I used it to migrate photos from one flickr stream to another with no trouble at all. You’ve saved me so much trouble! I have a question, though (sorry if this isn’t the right place to post it) – I’m unable to use Migratr for my Picasa photos which were pulled from my blogger photos – is there something else I need to do? Authentication is fine. When I choose the folder to import to, nothing happens after I click ‘ok’. Then there’s eventually a ’success’ pop up saying that my photos were uploaded, but there are no photos there. Thanks for any help, and again, thanks so much for this fantastic tool!

[...] – bookmarked by 2 members originally found by jp3dx on 2008-08-23 Killing the Fencepost in C#: A handy code snippet http://www.callingshotgun.net/geekery/killing-the-fencepost-in-c-a-handy-code-snippet/ – [...]

Does this create a secondary data structure?

Sorry just did a quick look, nothing schmancy.

Hi, just wanted to say thanks for the detailed before-and-after. I’m using C# a lot these days at work but yearn for the “functional” feel of python/ruby. Thanks.

Leave a comment