score:11

Accepted answer

Have you tried a simple join?..

if field.Values is already an array of strings then this should work fine.. otherwise you could use LINQ .ToArray() to convert the collection to an array.

string joined = string.Join(Environment.NewLine, field.Values);

VB

Dim joined As String = String.Join(Environment.NewLine, field.Values)

Just figured I would add, if you really, really just wanted to do this with LINQ a Aggregrate would work, although I wouldn't really recommend this for your needs.

field.Values.Aggregate(string.Empty, (s1, s2) => s1 += Environment.NewLine + s2);

score:0

If Values is a List you can do this...

field.Values.ForEach(o=>fileContent.Append(o + Environment.NewLine));

score:2

I created these extension methods that can be used to concatenate any number of items in a collection. It may be a bit overkill for you example, but if you need to concatenate items that are objects and not strings it can work great.

Usage:

fileContent = field.Values.Contatenate(Environment.NewLine);

Extensions:

public static class EnumerableExtensions
{
    public static string Concatenate<T>(this IEnumerable<T> source, string seperator)
    {
        return Concatenate(source, i => i.ToString(), seperator);
    }

    public static string Concatenate<T>(this IEnumerable<T> source, Func<T, string> selector, string seperator)
    {
        var builder = new StringBuilder();
        foreach (var item in source)
        {
            if (builder.Length > 0)
                builder.Append(seperator);

            builder.Append(selector(item));
        }
        return builder.ToString();
    }

    public static string ToCsv<T>(this IEnumerable<T> source)
    {
        return Concatenate(source, i => i.ToString(), ",");
    }

    public static string ToCsv<T>(this IEnumerable<T> source, Func<T, string> selector)
    {
        return Concatenate(source, selector, ",");
    }
}

score:1

You can use the Aggregate method to get there, but it won't be nearly as efficient as a foreach loop that Appends to a file or StringBuilder.

I believe your basic issue is that Linq's proper usage is to return results. The designers did not intend for you to use a Linq statement to modify the objects it is iterating through. That likely explains the general difficulty you've had with this task.

Don't forget that foreach is a proper way to use Linq results!

score:0

You may want to use IEnumerable.Aggregate.

Your code will look something like this:

Dim fileContentString As String = _
        field.Values.Aggregate(Function(ByVal JoinedValues, ByVal DiscreteValue) 
            JoinedValues & Environment.NewLine & DiscreteValue)

Disclaimer - Just because you CAN use Linq, doesn't mean it's the right tool for this job. As others have pointed out, a ForEach loop would be more efficient.

score:1

You can use a StringBuilder in the Aggregate extension method:

Dim fileContent As String = _
   field.Values.Aggregate( _
      New StringBuilder(), _
      Function(b, i) b.AppendLine(i) _
   ).ToString()

score:0

Create an extension method -

<Extension()> _
Public Function Flatten(ByVal stringList As IList(Of String), ByVal delimiter As String) As String
        Dim strB As New StringBuilder

        For Each Str As String In stringList
            If strB.ToString.Length > 0 Then
                strB.Append(delimiter)
            End If
            strB.Append(Str)
        Next
        Return strB.ToString
    End Function

Once you have that, you can simple do what you want like this -

Dim letters as New List(Of String)
'do your loading of the list

Dim formattedString As String = letters.Flatten(Environment.NewLine)

score:1

Note that .NET 4.0 includes a new String.Concat<T>() static method which takes an IEnumerable<T> and calls ToString on each object in the list. Should come in handy!


Related Articles