Создание списка через запятую из IList <string>или IEnumerable <string> - PullRequest
759 голосов
/ 28 апреля 2009

Каков самый чистый способ создания списка строковых значений через запятую из IList<string> или IEnumerable<string>?

String.Join(...) работает на string[], поэтому может быть неудобно работать, когда такие типы, как IList<string> или IEnumerable<string>, не могут быть легко преобразованы в строковый массив.

Ответы [ 21 ]

1290 голосов
/ 28 апреля 2009

.NET 4 +

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

Detail & Pre .Net 4.0 Solutions

IEnumerable<string> можно преобразовать в строковый массив очень легко с помощью LINQ (.NET 3.5):

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

Достаточно просто написать эквивалентный вспомогательный метод, если вам нужно:

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

Тогда назовите это так:

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

Затем вы можете позвонить string.Join. Конечно, у вас нет для использования вспомогательного метода:

// 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());

Последний немного глоток:)

Вероятно, это будет самый простой способ сделать это, а также довольно производительный - есть другие вопросы о том, на что именно похожа производительность, включая (но не ограничиваясь) этот .

Начиная с .NET 4.0, в string.Join доступно больше перегрузок, поэтому вы можете просто написать:

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

Намного проще:)

174 голосов
/ 18 июня 2010

FYI. Версия .NET 4.0 для string.Join() имеет некоторые дополнительные перегрузки , которые работают с IEnumerable вместо просто массивов, включая тот, который может работать с любым типом T:

public static string Join(string separator, IEnumerable<string> values)
public static string Join<T>(string separator, IEnumerable<T> values)
62 голосов
/ 28 апреля 2009

Самый простой способ сделать это - использовать метод LINQ Aggregate:

string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)
31 голосов
/ 05 августа 2010

Я думаю, что самый простой способ создать список строковых значений через запятую - просто:

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

Вот полный пример:

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

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

Нет необходимости создавать вспомогательную функцию, она встроена в .NET 4.0 и выше.

10 голосов
/ 04 мая 2017

Сравнивая по производительности, победителем становится «Зациклись, сб. Добавь и сделай шаг назад». На самом деле «перечислимое и ручное перемещение далее» - это то же самое, что хорошо (рассмотрим 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 |

Код:

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 было использовано

10 голосов
/ 20 августа 2016

Поскольку я пришел сюда при поиске объединения по определенному свойству списка объектов (а не его ToString ()), вот дополнение к принятому ответу:

var commaDelimited = string.Join(",", students.Where(i => i.Category == studentCategory)
                                 .Select(i => i.FirstName));
9 голосов
/ 18 июня 2010

Вот еще один метод расширения:

    public static string Join(this IEnumerable<string> source, string separator)
    {
        return string.Join(separator, source);
    }
8 голосов
/ 18 июня 2010

Я немного опоздал на эту дискуссию, но это мой вклад. У меня есть IList<Guid> OrderIds для преобразования в строку CSV, но ниже приведен общий и работает без изменений с другими типами:

string csv = OrderIds.Aggregate(new StringBuilder(),
             (sb, v) => sb.Append(v).Append(","),
             sb => {if (0 < sb.Length) sb.Length--; return sb.ToString();});

Short и sweet, использует StringBuilder для создания новой строки, сокращает длину StringBuilder на единицу, чтобы удалить последнюю запятую, и возвращает строку CSV.

Я обновил это, чтобы использовать несколько Append() для добавления строки + запятая. Из отзывов Джеймса я использовал Reflector, чтобы взглянуть на StringBuilder.AppendFormat(). Оказывается, AppendFormat() использует StringBuilder для построения строки формата, что делает ее менее эффективной в этом контексте, чем просто использование нескольких Appends().

7 голосов
/ 19 декабря 2013

Конкретная потребность, когда мы должны окружать ', например:

        string[] arr = { "jj", "laa", "123" };
        List<string> myList = arr.ToList();

        // 'jj', 'laa', '123'
        Console.WriteLine(string.Join(", ",
            myList.ConvertAll(m =>
                string.Format("'{0}'", m)).ToArray()));
7 голосов
/ 04 августа 2010

Вот как я это сделал, используя то, как я это делал на других языках:

private string ToStringList<T>(IEnumerable<T> list, string delimiter)
{
  var sb = new StringBuilder();
  string separator = String.Empty;
  foreach (T value in list)
  {
    sb.Append(separator).Append(value);
    separator = delimiter;
  }
  return sb.ToString();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...