views:

1655

answers:

7

What is the functional programming approach to convert an IEnumerable to a delimited string? I know I can use a loop, but I'm trying to wrap my head around functional programming.

Here's my example:
var selectedValues = from ListItem item in checkboxList.Items where item.Selected select item.Value;

var delimitedString = ??

...Or could I do this in just the first var assignment (append each result to the previous)?

+13  A: 
string.Join(", ", string[] enumerable)
Tom Ritter
+1, but I'd say string.Join(", ", selectedValues.ToArray())
Lucas
@Lucas, not if you're using .NET 4. http://msdn.microsoft.com/en-us/library/dd992421.aspx
Omer Raviv
@Omer, true! but this was back in Oct 2008, before .NET 4 :)
Lucas
+3  A: 
var delimitedString = string.Join(",", checkboxList.Items.Where(i => i.Selected).Select(i => i.Value).ToArray());
Justice
+1  A: 

Well, in this case the functional approach might not be best suited, simply because there isn't a LINQ "ForEach", and you don't want to use string concatenation: you want to use StringBuilder. You could use ToArray (an example just appeared above), but I'd be tempted to simply use:

    StringBuilder sb = new StringBuilder();
    foreach(ListViewItem item in checkboxList.SelectedItems) {
        if(sb.Length > 0) sb.Append(',');
        sb.Append(item.Text);
    }
    string s = sb.ToString();

Not functional programming, but it works... of course, if your source is already a string[] then string.Join is perfect. (LINQ is a great tool, but not necessarily always the best tool for every job)

Marc Gravell
+8  A: 
var delimitedString = selectedValues.Aggregate((x,y) => x + ", " + y);
Ilya Ryzhenkov
That will be very expensive in terms of intermediate strings. Very FP, but not very practical.http://www.yoda.arachsys.com/csharp/stringbuilder.html
Marc Gravell
@Marc, I answered the question asked, it was about FP, not about performance.
Ilya Ryzhenkov
A: 

Here's a LINQ/functional way of doing it.


string[] toDelimit = CallSomeFunction();
return toDelimit.Aggregate((x, y) => x + "," + y);
JaredPar
+3  A: 

AviewAnew is the best answer, but if what you are looking for is learning how to think in functional, what you should do is use a fold operation (or aggregate as it is called in NET).

items.Aggregate((accum, elem) => accum + ", " + elem);
Santiago Palladino
Is string.join better for performance reasons? I would say it is better from a readability stand-point.
Jeremy
I'd say yes; .ToArray() [to get the string[]] will use doubling, so not many intermediate arrays - and then string.Join is essentially StringBuilder; however, string concatenation will have a new string each time, so telescoping in size.
Marc Gravell
Agree, this is the kind of solution you would find in a functional programming language (such as haskell), but not here. But grasping foldr is one of the keys to master functional languages.
Santiago Palladino
So, is this an example of why functional languages are not generally as performant?
Jeremy
+16  A: 

Here's an example with a StringBuilder. The nice thing is that Append() returns the StringBuilder instance itself.

  return list.Aggregate( new StringBuilder(), 
                               ( sb, s ) => 
                               ( sb.Length == 0 ? sb : sb.Append( ',' ) ).Append( s ) );
Danko Durbić