¡TAN rocas! ¡Obtuve estas 3 excelentes respuestas en 10 minutos un domingo!
Riri
4
A partir de .NET 4.0ahí, existen métodos que toman una matriz de objetos y un IEnumerable para que pueda hacerlo string.join(",", number). Sé que la pregunta especifica .NET 3.5, así que no hice de esto una respuesta, pero aparece en búsquedas que no especifican una versión y saber que es posible en 4.0 podría ayudar a alguien.
Jason Goemaat
Respuestas:
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"
EDITAR : A partir de (al menos) .NET 4.5,
var result =string.Join(",", ints.Select(x => x.ToString()).ToArray());
es equivalente a:
var result =string.Join(",", ints);
EDITAR :
Veo varias soluciones que anuncian el uso de StringBuilder. Alguien se queja de que el método Join debería tomar un argumento IEnumerable.
Te voy a decepcionar :) String.Join requiere una matriz por una única razón: rendimiento. El método de unión necesita conocer el tamaño de los datos para preasignar eficazmente la cantidad de memoria necesaria.
Aquí hay una parte de la implementación interna del método 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]);}}
Soy demasiado vago para comparar el rendimiento de los métodos sugeridos. Pero algo me dice que Join ganará :)
Esta es probablemente la mejor apuesta usando métodos de extensión .NET centrales, pero realmente deseaba que string.Join () aceptara un IEnumerable <string> para evitar la conversión ToArray ().
spoulson
Nada evita que alguien sobrecargue la cadena. Únase para tomar un IEnumerable, también. ;)
Robert P
1
Esta es probablemente también la solución más fácil, y no solo la más rápida.
Encuentro que hay otros casos en los que el uso de las funciones Convert.xxx es una alternativa más ordenada a una lambda, aunque en C # 3 la lambda podría ayudar a la inferencia de tipos.
Una versión bastante compacta de C # 3 que funciona con .NET 2.0 es la siguiente:
Una mezcla de los dos enfoques sería escribir un método de extensión en IEnumerable <T> que usa un StringBuilder. Aquí hay un ejemplo, con diferentes sobrecargas dependiendo de si desea especificar la transformación o simplemente confiar en ToString simple. He nombrado el método "JoinStrings" en lugar de "Join" para evitar confusiones con el otro tipo de Join. Quizás alguien pueda pensar en un nombre mejor :)
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"),","));}}
¡Buena solución! Sin embargo, no necesita el parámetro de proyección, solo puede escribir x.Select (i => i.ToString ("X")). JoinStrings (";") que es más idiomático.
JacquesB
Sí, pensé en eso después. De vez en cuando es bueno poder especificarlo todo de una vez, pero definitivamente es más elegante dividir las operaciones :)
Tenemos que convertir cada uno de los elementos a Stringantes de poder unirlos, por lo que tiene sentido usar Selectuna expresión lambda. Esto es equivalente a mapen algunos otros idiomas. Luego tenemos que convertir la colección resultante de cadenas de nuevo en una matriz, porque String.Joinsolo acepta una matriz de cadenas.
El ToArray()es un poco feo que pienso. String.Joinrealmente debería aceptar IEnumerable<String>, no hay razón para restringirlo solo a matrices. Esto probablemente se deba a que Joines anterior a los genéricos, cuando las matrices eran el único tipo de colección con tipo disponible.
Editar: Cuando publiqué esto, tenía la impresión errónea de que "StringBuilder.Append (int value)" logró agregar internamente la representación de cadena del valor entero sin crear un objeto de cadena. Esto es incorrecto: inspeccionar el método con Reflector muestra que simplemente agrega value.ToString ().
Por lo tanto, la única diferencia de rendimiento potencial es que esta técnica evita la creación de una matriz y libera las cadenas para la recolección de basura un poco antes. En la práctica, esto no hará ninguna diferencia medible, así que voté a favor de esta mejor solución .
¿Lo has medido para que sea más rápido? String.Join también usa un StringBuilder.
JacquesB
Sí, pero primero debe convertir todo en una matriz, lo que está lejos de ser ideal. En particular, significa que debe tener todas las cadenas convertidas en la memoria al mismo tiempo, antes de comenzar a construir la cadena resultante.
Jon Skeet
OTOH String.Join precalcula el tamaño del búfer StringBuilder para evitar el cambio de tamaño. Por lo tanto, podría ser más rápido incluso si requiere más memoria.
JacquesB
5
La pregunta es cuál es la "forma más sencilla de convertirlos en una sola cadena donde los números están separados por un carácter".
La forma más sencilla es:
int[] numbers =newint[]{2,3,6,7};string number_string =string.Join(",", numbers);// do whatever you want with your exciting new number string
EDITAR: Esto solo funciona en .NET 4.0+, me perdí el requisito de .NET 3.5 la primera vez que leí la pregunta.
Es un método sobrecargado: msdn.microsoft.com/en-us/library/dd988350 Acabo de copiar el código que escribí en una nueva aplicación de consola, agregué una Console.WriteLine y esta es la salida: 2,3,6,7
WebMasterP
1
Creo que esto está disponible solo en .net 4
Govind Malviya
Requiere una matriz de objetos (o matriz de cadenas), no una matriz int. Dará un error de "la llamada es ambigua".
LarryBud
2
Estoy de acuerdo con la expresión lambda por legibilidad y mantenibilidad, pero no siempre será la mejor opción. La desventaja de usar los enfoques IEnumerable / ToArray y StringBuilder es que tienen que hacer crecer dinámicamente una lista, ya sea de elementos o caracteres, ya que no saben cuánto espacio se necesitará para la cadena final.
Si se da el raro caso de que la velocidad sea más importante que la concisión, lo siguiente es más eficiente.
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);
Gracias, agregué Substring(1)para arreglar eso (era de memoria).
anulado el
2
En .NET 4.0, la combinación de cadenas tiene una sobrecarga para params object[], por lo que es tan simple como:
int[] ids =newint[]{1,2,3};string.Join(",", ids);
ejemplo
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));
En .NET 2.0, es un poquito más difícil, ya que no existe tal sobrecarga. Entonces necesitas tu propio método genérico:
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;}
En .NET 3.5, puede utilizar métodos de extensión:
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;}}
Entonces puede usar el método de extensión JoinArray.
También puede usar ese método de extensión en .NET 2.0, si agrega ExtensionAttribute a su código:
// 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
ahí, existen métodos que toman una matriz de objetos y un IEnumerable para que pueda hacerlostring.join(",", number)
. Sé que la pregunta especifica .NET 3.5, así que no hice de esto una respuesta, pero aparece en búsquedas que no especifican una versión y saber que es posible en 4.0 podría ayudar a alguien.Respuestas:
EDITAR : A partir de (al menos) .NET 4.5,
es equivalente a:
EDITAR :
Veo varias soluciones que anuncian el uso de StringBuilder. Alguien se queja de que el método Join debería tomar un argumento IEnumerable.
Te voy a decepcionar :) String.Join requiere una matriz por una única razón: rendimiento. El método de unión necesita conocer el tamaño de los datos para preasignar eficazmente la cantidad de memoria necesaria.
Aquí hay una parte de la implementación interna del método String.Join:
Soy demasiado vago para comparar el rendimiento de los métodos sugeridos. Pero algo me dice que Join ganará :)
fuente
using System.Linq;
es requerido.Aunque el OP especificó .NET 3.5, las personas que quieran hacer esto en .NET 2.0 con C # 2 pueden hacer esto:
Encuentro que hay otros casos en los que el uso de las funciones Convert.xxx es una alternativa más ordenada a una lambda, aunque en C # 3 la lambda podría ayudar a la inferencia de tipos.
Una versión bastante compacta de C # 3 que funciona con .NET 2.0 es la siguiente:
fuente
Una mezcla de los dos enfoques sería escribir un método de extensión en IEnumerable <T> que usa un StringBuilder. Aquí hay un ejemplo, con diferentes sobrecargas dependiendo de si desea especificar la transformación o simplemente confiar en ToString simple. He nombrado el método "JoinStrings" en lugar de "Join" para evitar confusiones con el otro tipo de Join. Quizás alguien pueda pensar en un nombre mejor :)
fuente
Tenemos que convertir cada uno de los elementos a
String
antes de poder unirlos, por lo que tiene sentido usarSelect
una expresión lambda. Esto es equivalente amap
en algunos otros idiomas. Luego tenemos que convertir la colección resultante de cadenas de nuevo en una matriz, porqueString.Join
solo acepta una matriz de cadenas.El
ToArray()
es un poco feo que pienso.String.Join
realmente debería aceptarIEnumerable<String>
, no hay razón para restringirlo solo a matrices. Esto probablemente se deba a queJoin
es anterior a los genéricos, cuando las matrices eran el único tipo de colección con tipo disponible.fuente
Si su matriz de números enteros puede ser grande, obtendrá un mejor rendimiento con StringBuilder. P.ej:
Editar: Cuando publiqué esto, tenía la impresión errónea de que "StringBuilder.Append (int value)" logró agregar internamente la representación de cadena del valor entero sin crear un objeto de cadena. Esto es incorrecto: inspeccionar el método con Reflector muestra que simplemente agrega value.ToString ().
Por lo tanto, la única diferencia de rendimiento potencial es que esta técnica evita la creación de una matriz y libera las cadenas para la recolección de basura un poco antes. En la práctica, esto no hará ninguna diferencia medible, así que voté a favor de esta mejor solución .
fuente
La pregunta es cuál es la "forma más sencilla de convertirlos en una sola cadena donde los números están separados por un carácter".
La forma más sencilla es:
EDITAR: Esto solo funciona en .NET 4.0+, me perdí el requisito de .NET 3.5 la primera vez que leí la pregunta.
fuente
Estoy de acuerdo con la expresión lambda por legibilidad y mantenibilidad, pero no siempre será la mejor opción. La desventaja de usar los enfoques IEnumerable / ToArray y StringBuilder es que tienen que hacer crecer dinámicamente una lista, ya sea de elementos o caracteres, ya que no saben cuánto espacio se necesitará para la cadena final.
Si se da el raro caso de que la velocidad sea más importante que la concisión, lo siguiente es más eficiente.
fuente
También pensé que había una forma más sencilla. No sé sobre rendimiento, ¿alguien tiene alguna idea (teórica)?
fuente
Substring(1)
para arreglar eso (era de memoria).En .NET 4.0, la combinación de cadenas tiene una sobrecarga para
params object[]
, por lo que es tan simple como:ejemplo
En .NET 2.0, es un poquito más difícil, ya que no existe tal sobrecarga. Entonces necesitas tu propio método genérico:
En .NET 3.5, puede utilizar métodos de extensión:
Entonces puede usar el método de extensión JoinArray.
También puede usar ese método de extensión en .NET 2.0, si agrega ExtensionAttribute a su código:
fuente
Tu puedes hacer
Revisa
ToString delimitado por separador para matriz, lista, diccionario, IEnumerable genérico
fuente