var ints = new int[] {1, 2, 3, 4, 5};
var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());
Console.WriteLine(result); // prints "1,2,3,4,5"
РЕДАКТИРОВАНИЕ :
я вижу, что несколько решений рекламируют использование StringBuilder. Кто-то жалобы, что метод Join должен взять аргумент IEnumerable.
я собираюсь разочаровать Вас:) Строка. Join требует массива по единственной причине - производительность. Метод Join должен знать, что размер данных эффективно предварительно выделяет необходимый объем памяти.
Вот часть внутренней реализации Строки. Метод Join:
// length computed from length of items in input array and length of separator
string str = FastAllocateString(length);
fixed (char* chRef = &str.m_firstChar) // note than we use direct memory access here
{
UnSafeCharBuffer buffer = new UnSafeCharBuffer(chRef, length);
buffer.AppendString(value[startIndex]);
for (int j = startIndex + 1; j <= num2; j++)
{
buffer.AppendString(separator);
buffer.AppendString(value[j]);
}
}
я слишком ленив для сравнения производительности предложенных методов. Но что-то мне подсказывает, что Join победит:)
Хотя OP определил.NET 3.5, люди, желающие сделать, это в.NET 2.0 с C#2 может сделать это:
string.Join(",", Array.ConvertAll<int, String>(ints, Convert.ToString));
я нахожу, что существует много других случаев, где использование функций Convert.xxx является более опрятной альтернативой лямбде, хотя в C#3 лямбда могла бы помочь выводу типа.
А довольно компактная версия C#3, которая работает с.NET 2.0, является этим:
string.Join(",", Array.ConvertAll(ints, item => item.ToString()))
Одна смесь двух подходов должна была бы записать дополнительный метод на IEnumerable< T>, который использовал StringBuilder. Вот пример с различными перегрузками в зависимости от того, хотите ли Вы определить преобразование или просто полагаться на плоскость ToString. Я назвал метод "JoinStrings" вместо "Соединения" для предотвращения беспорядка с другим типом Соединения. Возможно, кто-то может придумать лучшее имя:)
using System;
using System.Collections.Generic;
using System.Text;
public static class Extensions
{
public static string JoinStrings<T>(this IEnumerable<T> source,
Func<T, string> projection, string separator)
{
StringBuilder builder = new StringBuilder();
bool first = true;
foreach (T element in source)
{
if (first)
{
first = false;
}
else
{
builder.Append(separator);
}
builder.Append(projection(element));
}
return builder.ToString();
}
public static string JoinStrings<T>(this IEnumerable<T> source, string separator)
{
return JoinStrings(source, t => t.ToString(), separator);
}
}
class Test
{
public static void Main()
{
int[] x = {1, 2, 3, 4, 5, 10, 11};
Console.WriteLine(x.JoinStrings(";"));
Console.WriteLine(x.JoinStrings(i => i.ToString("X"), ","));
}
}
String.Join(";", number.Select(item => item.ToString()).ToArray());
Мы должны преобразовать каждый из объектов к String
, прежде чем мы сможем присоединиться к ним, таким образом, имеет смысл использовать Select
и лямбда-выражение. Это эквивалентно map
на некоторых других языках. Тогда мы должны преобразовать получающийся набор строки назад к массиву, потому что String.Join
только принимает массив строк.
Эти ToArray()
немного ужасно, я думаю. String.Join
должен действительно принять IEnumerable<String>
, нет никакой причины ограничить его только массивами. Это, вероятно, просто, потому что Join
до дженериков, когда массивы были единственным видом введенного доступного набора.
Если Ваш массив целых чисел может быть большим, Вы получите лучшую производительность с помощью StringBuilder. Например:
StringBuilder builder = new StringBuilder();
char separator = ',';
foreach(int value in integerArray)
{
if (builder.Length > 0) builder.Append(separator);
builder.Append(value);
}
string result = builder.ToString();
Редактирование: Когда я отправил это, у меня создался ошибочное впечатление тот "StringBuilder. Добавьте (международное значение)" внутренне сумел добавить строковое представление целочисленного значения, не создавая строковый объект. Это неправильно: осмотр метода с Отражателем показывает, что это просто добавляет значение. ToString ().
Поэтому единственное потенциальное различие в производительности - то, что эта техника избегает одного создания массива и освобождает строки для сборки "мусора" немного раньше. На практике это не будет иметь никакого измеримого значения, таким образом, у меня будет upvoted это лучшее решение .
Я соглашаюсь с лямбда-выражением для удобочитаемости и пригодности для обслуживания, но это не всегда будет наилучший вариант. Оборотная сторона к использованию и IEnumerable/ToArray и подходы StringBuilder - то, что они должны динамично вырастить список, или объектов или символов, так как они не знают, сколько пространства будет необходимо для заключительной строки.
, Если редкий случай, где скорость более важна, чем краткость, следующее, более эффективен.
int[] number = new int[] { 1, 2, 3, 4, 5 };
string[] strings = new string[number.Length];
for (int i = 0; i < number.Length; i++)
strings[i] = number[i].ToString();
string result = string.Join(",", strings);
Можно сделать
ints.ToString(",")
ints.ToString("|")
ints.ToString(":")
Выезд
Разделитель Разграниченный ToString для Массива, Списка, Словаря, Универсального IEnumerable
ints.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);
Я тоже подумал, что есть более простой способ. Не знаю о производительности, у кого-нибудь есть (теоретические) идеи?