Conversión de una lista <int> en una cadena separada por comas

116

¿Hay alguna forma de tomar una lista y convertirla en una cadena separada por comas?

Sé que puedo hacer un bucle y construirlo, pero de alguna manera creo que algunos de ustedes son una forma más genial de hacerlo.

Realmente quiero aprender este tipo de 'trucos', así que explique o enlace a los documentos sobre el método que usa.

mrblah
fuente

Respuestas:

189
List<int> list = ...;
string.Join(",", list.Select(n => n.ToString()).ToArray())
Pavel Minaev
fuente
7
Inteligente pero lento e hinchado, ya que asigna una cadena por elemento. Usar un StringBuilder sería mucho más eficiente.
Steven Sudit
3
Por lo que vi en línea (búsqueda rápida) String.Join es más rápido que usar un StringBuilder.
Yuriy Faktorovich
3
stackoverflow.com/questions/585860/… , eres incorrecto Steven
Yuriy Faktorovich
6
Creo que Steven se refiere a la parte n.ToString () en lugar de a String.Join.
Larsenal
9
Larsenal: pero StringBuilder.Append (Int32) llama internamente a ToString en el entero de todos modos. StringBuilder no evita mágicamente el costo de asignar una cadena para cada elemento; simplemente lo esconde muy bien fuera de la vista.
itowlson
115

La solución simple es

List<int> list = new List<int>() {1,2,3};
string.Join<int>(",", list)

Lo usé hace un momento en mi código, funcionando en funtastic.

Nitin Daware
fuente
1
¡Gracias! este es un enfoque hermoso
Irfan Ashraf
2
Este es un enfoque mejor que el de respuesta aceptada. Con este enfoque, no tiene que importar Linq y esto es más rápido.
JoKeRxbLaCk
¡Frio! Nunca supe la cadena. Join tiene sobrecargas genéricas. Gracias.
mrmashal
10
List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(String.Join(",", list.Select(i => i.ToString()).ToArray()));
Yuriy Faktorovich
fuente
Genial si no puede usar .NET 4
Greg Woods
6

Para obtener aproximadamente un millón de soluciones a una versión un poco más complicada de este problema, muchas de las cuales son lentas, con errores o ni siquiera se compilan, consulte los comentarios de mi artículo sobre este tema:

http://blogs.msdn.com/ericlippert/archive/2009/04/15/comma-quibbling.aspx

y el comentario de StackOverflow:

El desafío de Eric Lippert "sutilezas por comas", ¿la mejor respuesta?

Eric Lippert
fuente
Gracias por el enlace. ¡Este problema de concatenación de cadenas ha resultado ser más complejo y más educativo de lo que esperaba!
Steven Sudit
4

Para mayor frescura, haría de este un método de extensión en IEnumerable <T> para que funcione en cualquier IEnumerable:

public static class IEnumerableExtensions {
  public static string BuildString<T>(this IEnumerable<T> self, string delim = ",") {
    return string.Join(delim, self)        
  }
}

Úselo de la siguiente manera:

List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(list.BuildString(", "));
cdiggins
fuente
Dos posibles optimizaciones: 1) Agregue el delimitador después de cada elemento independientemente, luego elimine el adicional después de que finalice el ciclo. 2) Especifique una capacidad para StringBuilder.
Steven Sudit
1
Si extrae Reflector, resulta que Join suma las longitudes para calcular previamente el tamaño del búfer, y también "ceba la bomba" agregando la primera cadena fuera del bucle, y luego, dentro del bucle, agregando incondicionalmente el delimitador antes del siguiente cadena. Combinado con algunos trucos internos / inseguros, debería ser muy rápido.
Steven Sudit
@Steven: siguió tu consejo.
cdiggins
1
Codifica de forma rígida el delimitador en su extensión e ignora el valor pasado para un delimitador, y omitió el punto y coma. Debería serreturn string.Join(delim, self);
Andrew
1

Parece razonablemente rápido.

IList<int> listItem = Enumerable.Range(0, 100000).ToList();
var result = listItem.Aggregate<int, StringBuilder, string>(new StringBuilder(), (strBuild, intVal) => { strBuild.Append(intVal); strBuild.Append(","); return strBuild; }, (strBuild) => strBuild.ToString(0, strBuild.Length - 1));
Gregory
fuente
1

Mi entrada "inteligente":

        List<int> list = new List<int> { 1, 2, 3 };
        StringBuilder sb = new StringBuilder();
        var y = list.Skip(1).Aggregate(sb.Append(x.ToString()),
                    (sb1, x) =>  sb1.AppendFormat(",{0}",x));

        // A lot of mess to remove initial comma
        Console.WriteLine(y.ToString().Substring(1,y.Length - 1));

Simplemente no he descubierto cómo agregar condicionalmente la coma.

Larsenal
fuente
1
No escriba Selectcon efectos secundarios en la lambda. En este caso, ni siquiera está utilizando y, por lo que su Selectes esencialmente un foreach- así que escríbalo como tal.
Pavel Minaev
No estaba sugiriendo esto como una buena solución. OP quería algo más interesante que foreach.
Larsenal
Sí, pero abusar de Selectcomo foreachva más allá de "interesante" y en, bueno, "abuso". Un enfoque más interesante aquí sería usar Enumerable.Aggregatecon StringBuildercomo valor inicial; inténtelo.
Pavel Minaev
Buena idea. Tengo que salir, pero puedo darle una vuelta.
Larsenal
0

puede utilizar, la biblioteca System.Linq; Es más eficiente:

using System.Linq;
string str =string.Join(",", MyList.Select(x => x.NombreAtributo));
Maurico Bello
fuente