ТАК классно! Я получил эти 3 отличных ответа за 10 минут в воскресенье!
Riri
4
По .NET 4.0существуют методы , которые принимают массив объектов и IEnumerable , так что вы можете просто сделать string.join(",", number). Я знаю, что в вопросе указывается .NET 3.5, поэтому я не дал этого ответа, но он появляется при поиске, в котором не указывается версия, и знание того, что это возможно в 4.0, может кому-то помочь.
Джейсон Гоэмаат,
Ответы:
162
var ints =newint[]{1,2,3,4,5};var result =string.Join(",", ints.Select(x => x.ToString()).ToArray());Console.WriteLine(result);// prints "1,2,3,4,5"
РЕДАКТИРОВАТЬ : Начиная с (по крайней мере) .NET 4.5,
var result =string.Join(",", ints.Select(x => x.ToString()).ToArray());
эквивалентно:
var result =string.Join(",", ints);
ИЗМЕНИТЬ :
Я вижу, что несколько решений рекламируют использование StringBuilder. Кто-то жалуется, что метод Join должен принимать аргумент IEnumerable.
Я вас разочарую :) String.Join требует массив только по одной причине - производительности. Метод соединения должен знать размер данных, чтобы эффективно предварительно выделить необходимый объем памяти.
Вот часть внутренней реализации метода String.Join:
// length computed from length of items in input array and length of separatorstring str =FastAllocateString(length);fixed(char* chRef =&str.m_firstChar)// note than we use direct memory access here{UnSafeCharBuffer buffer =newUnSafeCharBuffer(chRef, length);
buffer.AppendString(value[startIndex]);for(int j = startIndex +1; j <= num2; j++){
buffer.AppendString(separator);
buffer.AppendString(value[j]);}}
Мне лень сравнивать производительность предложенных методов. Но что-то мне подсказывает, что победит Join :)
Вероятно, это лучший вариант использования основных методов расширения .NET, но мне очень хотелось, чтобы string.Join () принимала IEnumerable <string>, чтобы избежать преобразования ToArray ().
spoulson
Ничто не мешает кому-то перегрузить строку. Присоединяйтесь, чтобы взять IEnumerable. ;)
Роберт П.
1
Это, вероятно, также самое простое решение, а не только самое быстрое.
Я обнаружил, что есть ряд других случаев, когда использование функций Convert.xxx является более изящной альтернативой лямбда-выражению, хотя в C # 3 лямбда-функция может помочь в определении типа.
Вот довольно компактная версия C # 3, которая работает с .NET 2.0:
Одним из сочетаний этих двух подходов было бы написание метода расширения в IEnumerable <T>, который использовал бы StringBuilder. Вот пример с разными перегрузками в зависимости от того, хотите ли вы указать преобразование или просто полагаться на простой ToString. Я назвал метод «JoinStrings» вместо «Join», чтобы избежать путаницы с другим типом Join. Может кто-нибудь придумает название получше :)
using System;
using System.Collections.Generic;
using System.Text;publicstaticclassExtensions{publicstaticstringJoinStrings<T>(thisIEnumerable<T> source,Func<T,string> projection,string separator){StringBuilder builder =newStringBuilder();bool first =true;foreach(T element in source){if(first){
first =false;}else{
builder.Append(separator);}
builder.Append(projection(element));}return builder.ToString();}publicstaticstringJoinStrings<T>(thisIEnumerable<T> source,string separator){returnJoinStrings(source, t => t.ToString(), separator);}}classTest{publicstaticvoidMain(){int[] x ={1,2,3,4,5,10,11};Console.WriteLine(x.JoinStrings(";"));Console.WriteLine(x.JoinStrings(i => i.ToString("X"),","));}}
Хорошее решение! Однако вам не нужен параметр проекции, вы можете просто написать x.Select (i => i.ToString ("X")). JoinStrings (";"), что более идиоматично.
JacquesB
Да, я потом думал об этом. Иногда приятно иметь возможность указать все сразу, но определенно более элегантно разделить операции :)
Мы должны преобразовать каждый из элементов в a, Stringпрежде чем мы сможем присоединиться к ним, поэтому имеет смысл использовать Selectи лямбда-выражение. Это эквивалентно mapнекоторым другим языкам. Затем мы должны преобразовать полученную коллекцию строк обратно в массив, потому чтоString.Join принимает только массив строк.
ToArray()Немного некрасиво , я думаю. String.Joinдействительно должен принять IEnumerable<String>, нет причин ограничивать его только массивами. Вероятно, это просто потому, что Joinэто еще не все, когда массивы были единственным доступным типом коллекции.
Изменить: когда я опубликовал это, у меня сложилось ошибочное впечатление, что «StringBuilder.Append (int value)» внутренне удалось добавить строковое представление целочисленного значения без создания строкового объекта. Это неправильно: проверка метода с помощью Reflector показывает, что он просто добавляет value.ToString ().
Поэтому единственное возможное различие в производительности заключается в том, что этот метод позволяет избежать создания одного массива и несколько быстрее освобождает строки для сборки мусора. На практике это не будет иметь никакого измеримого значения, поэтому я проголосовал за это лучшее решение .
Вы измерили, чтобы он был быстрее? String.Join также использует StringBuilder.
JacquesB
Да, но сначала нужно преобразовать все в массив, что далеко от идеала. В частности, это означает, что вам нужно иметь в памяти все преобразованные строки одновременно, прежде чем вы начнете строить результирующую строку.
Джон Скит,
OTOH String.Join предварительно вычисляет размер буфера StringBuilder, чтобы избежать изменения размера. Так что это может быть быстрее, даже если для этого потребуется больше памяти.
JacquesB
5
Вопрос в том, чтобы «проще всего преобразовать их в одну строку, где числа разделены символом».
Самый простой способ:
int[] numbers =newint[]{2,3,6,7};string number_string =string.Join(",", numbers);// do whatever you want with your exciting new number string
EDIT: это работает только в .NET 4.0+, я пропустил требование .NET 3.5, когда впервые прочитал вопрос.
Требуется массив объектов (или массив строк), а не массив int. Выдает ошибку "вызов неоднозначен".
LarryBud
2
Я согласен с лямбда-выражением для удобства чтения и поддержки, но это не всегда будет лучшим вариантом. Обратной стороной использования обоих подходов IEnumerable / ToArray и StringBuilder является то, что они должны динамически увеличивать список, будь то элементы или символы, поскольку они не знают, сколько места потребуется для конечной строки.
Если это редкий случай, когда скорость важнее лаконичности, более эффективно следующее.
int[] number =newint[]{1,2,3,4,5};string[] strings =newstring[number.Length];for(int i =0; i < number.Length; i++)
strings[i]= number[i].ToString();string result =string.Join(",", strings);
Спасибо, я добавил, Substring(1)чтобы исправить это (это было по памяти).
недействительна
2
В .NET 4.0 у строкового соединения есть перегрузка params object[], поэтому это так просто, как:
int[] ids =newint[]{1,2,3};string.Join(",", ids);
пример
int[] ids =newint[]{1,2,3};System.Data.Common.DbCommand cmd =newSystem.Data.SqlClient.SqlCommand("SELECT * FROM some_table WHERE id_column IN (@bla)");
cmd.CommandText= cmd.CommandText.Replace("@bla",string.Join(",", ids));
В .NET 2.0 это немного сложнее, поскольку такой перегрузки нет. Итак, вам нужен собственный общий метод:
publicstaticstringJoinArray<T>(string separator, T[] inputTypeArray){string strRetValue =null;System.Collections.Generic.List<string> ls =newSystem.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 вы можете использовать методы расширения:
publicstaticclassArrayEx{publicstaticstringJoinArray<T>(this T[] inputTypeArray,string separator){string strRetValue =null;System.Collections.Generic.List<string> ls =newSystem.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.
Вы также можете использовать этот метод расширения в .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)]publicsealedclassExtensionAttribute:Attribute{}}
.NET 4.0
существуют методы , которые принимают массив объектов и IEnumerable , так что вы можете просто сделатьstring.join(",", number)
. Я знаю, что в вопросе указывается .NET 3.5, поэтому я не дал этого ответа, но он появляется при поиске, в котором не указывается версия, и знание того, что это возможно в 4.0, может кому-то помочь.Ответы:
РЕДАКТИРОВАТЬ : Начиная с (по крайней мере) .NET 4.5,
эквивалентно:
ИЗМЕНИТЬ :
Я вижу, что несколько решений рекламируют использование StringBuilder. Кто-то жалуется, что метод Join должен принимать аргумент IEnumerable.
Я вас разочарую :) String.Join требует массив только по одной причине - производительности. Метод соединения должен знать размер данных, чтобы эффективно предварительно выделить необходимый объем памяти.
Вот часть внутренней реализации метода String.Join:
Мне лень сравнивать производительность предложенных методов. Но что-то мне подсказывает, что победит Join :)
источник
using System.Linq;
необходимо.Хотя OP указал .NET 3.5, люди, желающие сделать это в .NET 2.0 с C # 2, могут сделать это:
Я обнаружил, что есть ряд других случаев, когда использование функций Convert.xxx является более изящной альтернативой лямбда-выражению, хотя в C # 3 лямбда-функция может помочь в определении типа.
Вот довольно компактная версия C # 3, которая работает с .NET 2.0:
источник
Одним из сочетаний этих двух подходов было бы написание метода расширения в IEnumerable <T>, который использовал бы StringBuilder. Вот пример с разными перегрузками в зависимости от того, хотите ли вы указать преобразование или просто полагаться на простой ToString. Я назвал метод «JoinStrings» вместо «Join», чтобы избежать путаницы с другим типом Join. Может кто-нибудь придумает название получше :)
источник
Мы должны преобразовать каждый из элементов в a,
String
прежде чем мы сможем присоединиться к ним, поэтому имеет смысл использоватьSelect
и лямбда-выражение. Это эквивалентноmap
некоторым другим языкам. Затем мы должны преобразовать полученную коллекцию строк обратно в массив, потому чтоString.Join
принимает только массив строк.ToArray()
Немного некрасиво , я думаю.String.Join
действительно должен принятьIEnumerable<String>
, нет причин ограничивать его только массивами. Вероятно, это просто потому, чтоJoin
это еще не все, когда массивы были единственным доступным типом коллекции.источник
Если ваш массив целых чисел может быть большим, вы получите лучшую производительность, используя StringBuilder. Например:
Изменить: когда я опубликовал это, у меня сложилось ошибочное впечатление, что «StringBuilder.Append (int value)» внутренне удалось добавить строковое представление целочисленного значения без создания строкового объекта. Это неправильно: проверка метода с помощью Reflector показывает, что он просто добавляет value.ToString ().
Поэтому единственное возможное различие в производительности заключается в том, что этот метод позволяет избежать создания одного массива и несколько быстрее освобождает строки для сборки мусора. На практике это не будет иметь никакого измеримого значения, поэтому я проголосовал за это лучшее решение .
источник
Вопрос в том, чтобы «проще всего преобразовать их в одну строку, где числа разделены символом».
Самый простой способ:
EDIT: это работает только в .NET 4.0+, я пропустил требование .NET 3.5, когда впервые прочитал вопрос.
источник
Я согласен с лямбда-выражением для удобства чтения и поддержки, но это не всегда будет лучшим вариантом. Обратной стороной использования обоих подходов IEnumerable / ToArray и StringBuilder является то, что они должны динамически увеличивать список, будь то элементы или символы, поскольку они не знают, сколько места потребуется для конечной строки.
Если это редкий случай, когда скорость важнее лаконичности, более эффективно следующее.
источник
Я тоже думал, что есть способ попроще. Не знаю о производительности, у кого-нибудь есть (теоретические) идеи?
источник
Substring(1)
чтобы исправить это (это было по памяти).В .NET 4.0 у строкового соединения есть перегрузка
params object[]
, поэтому это так просто, как:пример
В .NET 2.0 это немного сложнее, поскольку такой перегрузки нет. Итак, вам нужен собственный общий метод:
В .NET 3.5 вы можете использовать методы расширения:
Таким образом, вы можете использовать метод расширения JoinArray.
Вы также можете использовать этот метод расширения в .NET 2.0, если вы добавите ExtensionAttribute в свой код:
источник
Ты можешь сделать
Проверять, выписываться
Разделитель ToString с разделителями для массива, списка, словаря, универсального IEnumerable
источник
забудьте о .net 3.5 и используйте следующий код в ядре .net
источник