Conversion d'une liste <int> en une chaîne séparée par des virgules

116

Existe-t-il un moyen de prendre une liste et de la convertir en une chaîne séparée par des virgules?

Je sais que je peux juste faire une boucle et le construire, mais je pense que certains d'entre vous sont une façon plus cool de le faire?

Je veux vraiment apprendre ces types de «trucs», alors veuillez expliquer ou créer un lien vers la documentation sur la méthode que vous utilisez.

mrblah
la source

Réponses:

189
List<int> list = ...;
string.Join(",", list.Select(n => n.ToString()).ToArray())
Pavel Minaev
la source
7
Intelligent mais lent et gonflé, car il alloue une chaîne par élément. L'utilisation d'un StringBuilder serait beaucoup plus efficace.
Steven Sudit
3
D'après ce que j'ai vu en ligne (recherche rapide), String.Join est plus rapide que d'utiliser un StringBuilder.
Yuriy Faktorovich
3
stackoverflow.com/questions/585860/… , vous vous trompez Steven
Yuriy Faktorovich
6
Je pense que Steven fait référence à la partie n.ToString () plutôt qu'à String.Join.
Larsenal
9
Larsenal: mais StringBuilder.Append (Int32) appelle quand même ToString sur l'entier. StringBuilder n'évite pas comme par magie le coût d'allocation d'une chaîne pour chaque élément; il le range juste bien hors de vue.
itowlson
115

La solution simple est

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

Je l'ai utilisé tout à l'heure dans mon code, fonctionnant de manière funtastique.

Nitin Daware
la source
1
Remercier! c'est une belle approche
Irfan Ashraf
2
C'est une meilleure approche que la réponse acceptée. Avec cette approche, vous n'avez pas besoin d'importer Linq et c'est plus rapide.
JoKeRxbLaCk
Cool! Je n'ai jamais connu string.Join a des surcharges génériques. Merci.
mrmashal le
10
List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(String.Join(",", list.Select(i => i.ToString()).ToArray()));
Yuriy Faktorovich
la source
Parfait si vous ne pouvez pas utiliser .NET 4
Greg Woods
6

Pour environ un milliard de solutions à une version légèrement plus compliquée de ce problème - dont beaucoup sont lentes, boguées ou ne se compilent même pas - voir les commentaires de mon article sur ce sujet:

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

et le commentaire StackOverflow:

Le défi d'Eric Lippert "ergoter par la virgule", meilleure réponse?

Eric Lippert
la source
Merci pour le lien. Ce problème de concaténation de chaînes s'est avéré plus complexe et plus éducatif que je ne m'y attendais!
Steven Sudit
4

Pour plus de fraîcheur, je ferais de cette méthode une extension sur IEnumerable <T> afin qu'elle fonctionne sur n'importe quel IEnumerable:

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

Utilisez-le comme suit:

List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(list.BuildString(", "));
cdiggins
la source
Deux optimisations possibles: 1) Ajoutez le délimiteur après chaque élément, puis supprimez le délimiteur après la fin de la boucle. 2) Spécifiez une capacité pour le StringBuilder.
Steven Sudit
1
Si vous creusez Reflector, il s'avère que Join additionne les longueurs pour précalculer la taille du tampon, et "amorce également la pompe" en ajoutant la première chaîne à l'extérieur de la boucle, puis, à l'intérieur de la boucle, en ajoutant sans condition le délimiteur avant le chaîne suivante. Combiné avec quelques astuces non sûres / internes, cela devrait être très rapide.
Steven Sudit
@Steven: a suivi vos conseils.
cdiggins
1
Vous codez en dur le délimiteur dans votre extension et ignorez la valeur transmise pour un délimiteur et avez manqué le point-virgule. Ça devrait êtrereturn string.Join(delim, self);
Andrew
1

Cela semble raisonnablement rapide.

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));
Grégory
la source
1

Mon entrée "intelligente":

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

Je n'ai simplement pas compris comment ajouter conditionnellement la virgule.

Larsenal
la source
1
Veuillez ne pas écrire Selectavec des effets secondaires dans le lambda. Dans ce cas, vous n'utilisez même pas y, donc vous n'êtes Selectessentiellement qu'un foreach- alors écrivez-le comme tel.
Pavel Minaev
Je ne suggérais pas cela comme une bonne solution. OP voulait quelque chose de plus intéressant que foreach.
Larsenal
Ouais, mais abuser Selectcomme foreachça passe "intéressant" et dans, eh bien, "abuser". Une approche plus intéressante ici serait d'utiliser Enumerable.Aggregateavec StringBuildercomme valeur de départ - essayez cela.
Pavel Minaev
Bonne idée. Je dois sortir, mais je peux donner un tourbillon.
Larsenal
0

vous pouvez utiliser, la bibliothèque System.Linq; C'est plus efficace:

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