Coder Perfect

Using IListstring> or IEnumerablestring> to create a comma separated list

Problem

How do I make a comma-separated list of string values from an IListstring> or IEnumerablestring>?

String. Because Join(…) acts on a string[], it can be inconvenient to use when working with types like IListstring> or IEnumerablestring>, which aren’t easily turned into a string array.

Asked by Daniel Fortunov

Solution #1

.NET 4+

IList<string> strings = new List<string>{"1","2","testing"};
string joined = string.Join(",", strings);

Pre-.Net 4.0 Solutions & Details

With LINQ (.NET 3.5), IEnumerablestring> may be simply transformed to a string array:

IEnumerable<string> strings = ...;
string[] array = strings.ToArray();

If you need to, you can easily write the corresponding helper method:

public static T[] ToArray(IEnumerable<T> source)
{
    return new List<T>(source).ToArray();
}

Then call it something like this:

IEnumerable<string> strings = ...;
string[] array = Helpers.ToArray(strings);

After that, you can call string. Join. You don’t have to use a helper method, of course:

// C# 3 and .NET 3.5 way:
string joined = string.Join(",", strings.ToArray());
// C# 2 and .NET 2.0 way:
string joined = string.Join(",", new List<string>(strings).ToArray());

The latter, on the other hand, is a mouthful:)

This is probably the simplest method to accomplish it, and it’s also pretty performant – there are a few more queries concerning the performance, including (but not limited to) this one.

There are more overloads available in string since.NET 4.0. Join, and you’ll be able to write:

string joined = string.Join(",", strings);

Much simpler 🙂

Answered by Jon Skeet

Solution #2

String is the.NET 4.0 version, just in case you didn’t know. There are also more overloads for Join() that operate with IEnumerable instead of simply arrays, including one that can handle any type T:

public static string Join(string separator, IEnumerable<string> values)
public static string Join<T>(string separator, IEnumerable<T> values)

Answered by Xavier Poinas

Solution #3

The LINQ Aggregate method appears to be the simplest way to accomplish this:

string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)

Answered by Daniel Fortunov

Solution #4

The simplest way to build a comma-separated list of string values, in my opinion, is to type:

string.Join<string>(",", stringEnumerable);

Here’s a whole example:

IEnumerable<string> stringEnumerable= new List<string>();
stringList.Add("Comma");
stringList.Add("Separated");

string.Join<string>(",", stringEnumerable);

There’s no need to create a helper function because it’s already included in.NET 4.0 and higher.

Answered by Dan VanWinkle

Solution #5

When it comes to performance, the winner is “sb, loop it. Add it at the end and go backwards “.. “Enumerable and manual move next” is actually the same thing (consider stddev).

BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC
  [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
  Clr    : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
  Core   : .NET Core 4.6.25009.03, 64bit RyuJIT


                Method |  Job | Runtime |     Mean |     Error |    StdDev |      Min |      Max |   Median | Rank |  Gen 0 | Allocated |
---------------------- |----- |-------- |---------:|----------:|----------:|---------:|---------:|---------:|-----:|-------:|----------:|
            StringJoin |  Clr |     Clr | 28.24 us | 0.4381 us | 0.3659 us | 27.68 us | 29.10 us | 28.21 us |    8 | 4.9969 |   16.3 kB |
 SeparatorSubstitution |  Clr |     Clr | 17.90 us | 0.2900 us | 0.2712 us | 17.55 us | 18.37 us | 17.80 us |    6 | 4.9296 |  16.27 kB |
     SeparatorStepBack |  Clr |     Clr | 16.81 us | 0.1289 us | 0.1206 us | 16.64 us | 17.05 us | 16.81 us |    2 | 4.9459 |  16.27 kB |
            Enumerable |  Clr |     Clr | 17.27 us | 0.0736 us | 0.0615 us | 17.17 us | 17.36 us | 17.29 us |    4 | 4.9377 |  16.27 kB |
            StringJoin | Core |    Core | 27.51 us | 0.5340 us | 0.4995 us | 26.80 us | 28.25 us | 27.51 us |    7 | 5.0296 |  16.26 kB |
 SeparatorSubstitution | Core |    Core | 17.37 us | 0.1664 us | 0.1557 us | 17.15 us | 17.68 us | 17.39 us |    5 | 4.9622 |  16.22 kB |
     SeparatorStepBack | Core |    Core | 15.65 us | 0.1545 us | 0.1290 us | 15.45 us | 15.82 us | 15.66 us |    1 | 4.9622 |  16.22 kB |
            Enumerable | Core |    Core | 17.00 us | 0.0905 us | 0.0654 us | 16.93 us | 17.12 us | 16.98 us |    3 | 4.9622 |  16.22 kB |

Code:

public class BenchmarkStringUnion
{
    List<string> testData = new List<string>();
    public BenchmarkStringUnion()
    {
        for(int i=0;i<1000;i++)
        {
            testData.Add(i.ToString());
        }
    }
    [Benchmark]
    public string StringJoin()
    {
        var text = string.Join<string>(",", testData);
        return text;
    }
    [Benchmark]
    public string SeparatorSubstitution()
    {
        var sb = new StringBuilder();
        var separator = String.Empty;
        foreach (var value in testData)
        {
            sb.Append(separator).Append(value);
            separator = ",";
        }
        return sb.ToString();
    }

    [Benchmark]
    public string SeparatorStepBack()
    {
        var sb = new StringBuilder();
        foreach (var item in testData)
            sb.Append(item).Append(',');
        if (sb.Length>=1) 
            sb.Length--;
        return sb.ToString();
    }

    [Benchmark]
    public string Enumerable()
    {
        var sb = new StringBuilder();
        var e = testData.GetEnumerator();
        bool  moveNext = e.MoveNext();
        while (moveNext)
        {
            sb.Append(e.Current);
            moveNext = e.MoveNext();
            if (moveNext) 
                sb.Append(",");
        }
        return sb.ToString();
    }
}

https://github.com/dotnet/BenchmarkDotNet was used

Answered by Roman Pokrovskij

Post is based on https://stackoverflow.com/questions/799446/creating-a-comma-separated-list-from-iliststring-or-ienumerablestring