¿Cómo unir int a una cadena separada por caracteres en .NET?

Tengo una matriz de enteros:

int[] number = new int[] { 2,3,6,7 }; 

¿Cuál es la forma más fácil de convertirlos en una sola cadena donde los números están separados por un carácter (como: "2,3,6,7" )?

Estoy en C # y .NET 3.5.

 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" 

EDITAR :

Veo varias soluciones publicitar el uso de StringBuilder. Alguien se queja de que el método Join debería tomar un argumento IEnumerable.

Voy a decepcionarte 🙂 String.Join requiere una matriz por una sola razón: rendimiento. El método Join necesita conocer el tamaño de los datos para preasignar de manera efectiva la cantidad necesaria de memoria.

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 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]); } } 

Soy demasiado vago para comparar el rendimiento de los métodos sugeridos. Pero algo me dice que Join ganará 🙂

Aunque el OP especificó .NET 3.5, las personas que quieran hacer esto en .NET 2.0 con C # 2 pueden hacer esto:

 string.Join(",", Array.ConvertAll(ints, Convert.ToString)); 

Encuentro que hay otros casos en los que el uso de las funciones Convert.xxx es una alternativa más ordenada que una lambda, aunque en C # 3, la lambda podría ayudar a la inferencia de tipo.

Una versión bastante compacta de C # 3 que funciona con .NET 2.0 es esta:

 string.Join(",", Array.ConvertAll(ints, item => item.ToString())) 

Una mezcla de los dos enfoques sería escribir un método de extensión en IEnumerable que usó 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 encontrar un mejor nombre 🙂

 using System; using System.Collections.Generic; using System.Text; public static class Extensions { public static string JoinStrings(this IEnumerable source, Func 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(this IEnumerable 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()); 

Tenemos que convertir cada uno de los elementos en una String antes de que podamos unirlos, por lo que tiene sentido usar Select y una expresión lambda. Esto es equivalente al map en algunos otros idiomas. Luego, debemos convertir la colección resultante de cadena a una matriz, porque String.Join solo acepta una matriz de cadenas.

El ToArray() es un poco feo, creo. String.Join realmente debería aceptar IEnumerable , no hay ninguna razón para restringirlo solo a las matrices. Probablemente, esto se deba a que Join es anterior a los generics, cuando los arrays son el único tipo de colección tipada disponible.

Si su matriz de enteros puede ser grande, obtendrá un mejor rendimiento utilizando un StringBuilder. P.ej:

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

Editar: Cuando publiqué esto, estaba bajo la impresión equivocada de que “StringBuilder.Append (int value)” administraba internamente para agregar 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 supondrá ninguna diferencia medible, por lo que he votado a favor de esta mejor solución .

La pregunta es por “la forma más fácil de convertir estos en una sola cadena donde el número está separado por un personaje”.

La forma más fácil es:

 int[] numbers = new int[] { 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.

Estoy de acuerdo con la expresión lambda de legibilidad y mantenibilidad, pero no siempre será la mejor opción. La desventaja de utilizar 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 el raro caso en que la velocidad es más importante que la concisión, lo siguiente es más eficiente.

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

También pensé que había una manera más simple. No sé sobre el rendimiento, ¿alguien tiene alguna idea (teórica)?

En .NET 4.0, la unión de cadenas tiene una sobrecarga para el params object[] , por lo que es tan simple como:

 int[] ids = new int[] { 1, 2, 3 }; string.Join(",", ids); 

ejemplo

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

En .NET 2.0, es un poquito más difícil, ya que no hay tal sobrecarga. Entonces necesitas tu propio método genérico:

 public static string JoinArray(string separator, T[] inputTypeArray) { string strRetValue = null; System.Collections.Generic.List ls = new System.Collections.Generic.List(); 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 usar métodos de extensión:

 public static class ArrayEx { public static string JoinArray(this T[] inputTypeArray, string separator) { string strRetValue = null; System.Collections.Generic.List ls = new System.Collections.Generic.List(); 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.

 int[] ids = new int[] { 1, 2, 3 }; string strIdList = ids.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)] public sealed class ExtensionAttribute : Attribute {} } 

Tu puedes hacer

 ints.ToString(",") ints.ToString("|") ints.ToString(":") 

Revisa

Separator Delimited ToString for Array, List, Dictionary, IEnumerable genérico