10 ответов:
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"EDIT:
Я вижу несколько решений рекламировать использование StringBuilder. Кто-то жалуется, что метод Join должен принимать аргумент IEnumerable.
Я собираюсь разочаровать вас:) строка.Присоединение требует время для выполнения. Метод 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));Я считаю, есть ряд других случаев, когда использование преобразования.функции xxx-это более аккуратная альтернатива лямбда,хотя в C#3 лямбда может помочь в выводе типа.
довольно компактная версия C#3, которая работает с .NET 2.0, такова:
string.Join(",", Array.ConvertAll(ints, item => item.ToString()))
одним из двух подходов было бы написать метод расширения на IEnumerable
, который использовал StringBuilder. Вот пример, с различными перегрузками в зависимости от того, хотите ли вы указать преобразование или просто полагаться на простую ToString. Я назвал метод " JoinStrings "вместо" Join", чтобы избежать путаницы с другим типом соединения. Возможно, кто-то может придумать имя получше :) 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принимает только массив строк.The
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();Edit: когда я опубликовал это, у меня было ошибочное впечатление, что "StringBuilder.Append (int value)" внутренне удалось добавить строковое представление целочисленного значения без создания строкового объекта. Это неправильно: проверка метода с отражателем показывает, что он просто добавляет значение.ToString ().
поэтому единственный потенциал разница в производительности заключается в том, что этот метод позволяет избежать создания одного массива и освобождает строки для сборки мусора немного раньше. На практике это не будет иметь никакого измеримого значения, поэтому я поддержал это лучшим решением.
вопрос заключается в "простейшем способе преобразования их в одну строку, где число разделено символом".
самый простой способ сделать это:
int[] numbers = new int[] { 2,3,6,7 }; string number_string = string.Join(",", numbers); // do whatever you want with your exciting new number stringEDIT: это работает только в .NET 4.0+, я пропустил требование .NET 3.5 при первом чтении вопроса.
Я согласен с лямбда-выражением для удобочитаемости и ремонтопригодности, но это не всегда будет лучшим вариантом. Недостатком использования обоих подходов 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.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);Я тоже думал, что есть более простой способ. Не знаю о производительности, у кого-нибудь есть какая-то (теоретическая) идея?
в .NET 4.0 string join имеет перегрузку для
params object[], так что это так просто:int[] ids = new int[] { 1, 2, 3 }; string.Join(",", ids);пример
int[] ids = new int[] { 1, 2, 3 }; System.Data.Common.DbCommand cmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM some_table WHERE id_column IN (@bla)"); cmd.CommandText = cmd.CommandText.Replace("@bla", string.Join(",", ids));в .NET 2.0 это немного сложнее, так как нет такой перегрузки. Поэтому вам нужен свой собственный универсальный метод:
public static string JoinArray<T>(string separator, T[] inputTypeArray) { string strRetValue = null; System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>(); for (int i = 0; i < inputTypeArray.Length; ++i) { string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture); if (!string.IsNullOrEmpty(str)) { // SQL-Escape // if (typeof(T) == typeof(string)) // str = str.Replace("'", "''"); ls.Add(str); } // End if (!string.IsNullOrEmpty(str)) } // Next i strRetValue= string.Join(separator, ls.ToArray()); ls.Clear(); ls = null; return strRetValue; }в .NET 3.5 можно использовать методы расширения:
public static class ArrayEx { public static string JoinArray<T>(this T[] inputTypeArray, string separator) { string strRetValue = null; System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>(); for (int i = 0; i < inputTypeArray.Length; ++i) { string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture); if (!string.IsNullOrEmpty(str)) { // SQL-Escape // if (typeof(T) == typeof(string)) // str = str.Replace("'", "''"); ls.Add(str); } // End if (!string.IsNullOrEmpty(str)) } // Next i strRetValue= string.Join(separator, ls.ToArray()); ls.Clear(); ls = null; return strRetValue; } }таким образом, вы можете использовать расширение JoinArray-метод.
int[] ids = new int[] { 1, 2, 3 }; string strIdList = ids.JoinArray(",");вы также можете использовать этот метод расширения в .NET 2.0, если вы добавляете атрибут ExtensionAttribute в свой код:
// you need this once (only), and it must be in this namespace namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] public sealed class ExtensionAttribute : Attribute {} }
можно сделать
ints.ToString(",") ints.ToString("|") ints.ToString(":")проверить
разделитель с разделителями ToString для массива, списка, словаря, общего IEnumerable
Comments