TELLEMENT rock! J'ai eu ces 3 excellentes réponses en 10 minutes un dimanche!
Riri
4
À partir de .NET 4.0là, il existe des méthodes qui prennent un tableau d'objets et un IEnumerable, vous pouvez donc le faire string.join(",", number). Je sais que la question spécifie .NET 3.5, donc je n'en ai pas fait une réponse, mais cela apparaît dans les recherches qui ne spécifient pas de version et savoir que c'est possible dans 4.0 pourrait aider quelqu'un.
Jason Goemaat
Réponses:
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"
EDIT : à partir de (au moins) .NET 4.5,
var result =string.Join(",", ints.Select(x => x.ToString()).ToArray());
est équivalent à:
var result =string.Join(",", ints);
MODIFIER :
Je vois plusieurs solutions annoncer l'utilisation de StringBuilder. Quelqu'un se plaint que la méthode Join doit prendre un argument IEnumerable.
Je vais vous décevoir :) String.Join nécessite un tableau pour une seule raison: les performances. La méthode de jointure doit connaître la taille des données pour préallouer efficacement la quantité de mémoire nécessaire.
Voici une partie de l'implémentation interne de la méthode 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]);}}
Je suis trop paresseux pour comparer les performances des méthodes suggérées. Mais quelque chose me dit que Join gagnera :)
C'est probablement le meilleur pari en utilisant les méthodes d'extension de base .NET, mais j'aurais vraiment souhaité que string.Join () accepte un IEnumerable <string> pour éviter la conversion ToArray ().
spoulson
Rien n'empêche quelqu'un de surcharger la chaîne, mais aussi de prendre un IEnumerable. ;)
Robert P
1
C'est probablement aussi la solution la plus simple, et pas seulement la plus rapide.
Je trouve qu'il existe un certain nombre d'autres cas où l'utilisation des fonctions Convert.xxx est une alternative plus intéressante à un lambda, bien qu'en C # 3, le lambda puisse aider l'inférence de type.
Une version C # 3 assez compacte qui fonctionne avec .NET 2.0 est la suivante:
Un mélange des deux approches consisterait à écrire une méthode d'extension sur IEnumerable <T> qui utilise un StringBuilder. Voici un exemple, avec des surcharges différentes selon que vous souhaitez spécifier la transformation ou simplement compter sur ToString brut. J'ai nommé la méthode "JoinStrings" au lieu de "Join" pour éviter toute confusion avec l'autre type de Join. Peut-être que quelqu'un peut trouver un meilleur nom :)
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"),","));}}
Belle solution! Cependant, vous n'avez pas besoin du paramètre de projection, vous pouvez simplement écrire x.Select (i => i.ToString ("X")). JoinStrings (";") qui est plus idiomatique.
JacquesB
Oui, j'y ai pensé après. Parfois, c'est bien de pouvoir tout spécifier en une seule fois, mais il est nettement plus élégant de diviser les opérations :)
Nous devons convertir chacun des éléments en un Stringavant de pouvoir les joindre, il est donc logique d'utiliser Selectet une expression lambda. Ceci est équivalent à mapdans certaines autres langues. Ensuite, nous devons reconvertir la collection résultante de chaînes en un tableau, car String.Joinn'accepte qu'un tableau de chaînes.
Le ToArray()est un peu moche je trouve. String.Joindevrait vraiment accepter IEnumerable<String>, il n'y a aucune raison de le limiter aux seuls tableaux. C'est probablement juste parce que Joinc'est avant les génériques, quand les tableaux étaient le seul type de collection typée disponible.
Edit: Quand j'ai posté ceci, j'avais l'impression erronée que "StringBuilder.Append (valeur int)" a réussi en interne à ajouter la représentation sous forme de chaîne de la valeur entière sans créer d'objet string. C'est faux: l'inspection de la méthode avec Reflector montre qu'elle ajoute simplement value.ToString ().
Par conséquent, la seule différence de performances potentielle est que cette technique évite la création d'un tableau et libère les chaînes pour le garbage collection un peu plus tôt. En pratique, cela ne fera aucune différence mesurable, j'ai donc voté pour cette meilleure solution .
L'avez-vous mesuré pour être plus rapide? String.Join utilise également un StringBuilder.
JacquesB
Oui, mais vous devez d'abord convertir le tout en un tableau, ce qui est loin d'être idéal. En particulier, cela signifie que vous devez avoir toutes les chaînes converties en mémoire en même temps, avant de commencer à créer la chaîne résultante.
Jon Skeet
OTOH String.Join précalcule la taille du tampon StringBuilder afin d'éviter le redimensionnement. Cela pourrait donc être plus rapide même si cela nécessite plus de mémoire.
JacquesB
5
La question est de savoir "le moyen le plus simple de les convertir en une seule chaîne où les nombres sont séparés par un caractère".
Le moyen le plus simple est:
int[] numbers =newint[]{2,3,6,7};string number_string =string.Join(",", numbers);// do whatever you want with your exciting new number string
EDIT: Cela ne fonctionne que dans .NET 4.0+, j'ai manqué l'exigence .NET 3.5 la première fois que j'ai lu la question.
C'est une méthode surchargée: msdn.microsoft.com/en-us/library/dd988350 Je viens de copier le code que j'ai écrit dans une nouvelle application console, j'ai ajouté une Console.WriteLine et voici le résultat: 2,3,6,7
WebMasterP
1
Je pense que cela n'est disponible qu'en .net 4
Govind Malviya
Nécessite un tableau d'objets (ou un tableau de chaînes), pas un tableau int. Donnera une erreur "l'appel est ambigu".
LarryBud
2
Je suis d'accord avec l'expression lambda pour la lisibilité et la maintenabilité, mais ce ne sera pas toujours la meilleure option. L'inconvénient d'utiliser à la fois les approches IEnumerable / ToArray et StringBuilder est qu'ils doivent développer dynamiquement une liste, soit d'éléments, soit de caractères, car ils ne savent pas combien d'espace sera nécessaire pour la chaîne finale.
Si le cas rare où la vitesse est plus importante que la concision, ce qui suit est plus efficace.
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);
Merci, j'ai ajouté Substring(1)pour résoudre ce problème (c'était de mémoire).
annulé
2
Dans .NET 4.0, la jointure de chaîne a une surcharge pour params object[], donc c'est aussi simple que:
int[] ids =newint[]{1,2,3};string.Join(",", ids);
exemple
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));
Dans .NET 2.0, c'est un tout petit peu plus difficile, car il n'y a pas de telle surcharge. Vous avez donc besoin de votre propre méthode générique:
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;}
Dans .NET 3.5, vous pouvez utiliser des méthodes d'extension:
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;}}
Vous pouvez donc utiliser la méthode d'extension JoinArray.
Vous pouvez également utiliser cette méthode d'extension dans .NET 2.0, si vous ajoutez ExtensionAttribute à votre code:
// 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
là, il existe des méthodes qui prennent un tableau d'objets et un IEnumerable, vous pouvez donc le fairestring.join(",", number)
. Je sais que la question spécifie .NET 3.5, donc je n'en ai pas fait une réponse, mais cela apparaît dans les recherches qui ne spécifient pas de version et savoir que c'est possible dans 4.0 pourrait aider quelqu'un.Réponses:
EDIT : à partir de (au moins) .NET 4.5,
est équivalent à:
MODIFIER :
Je vois plusieurs solutions annoncer l'utilisation de StringBuilder. Quelqu'un se plaint que la méthode Join doit prendre un argument IEnumerable.
Je vais vous décevoir :) String.Join nécessite un tableau pour une seule raison: les performances. La méthode de jointure doit connaître la taille des données pour préallouer efficacement la quantité de mémoire nécessaire.
Voici une partie de l'implémentation interne de la méthode String.Join:
Je suis trop paresseux pour comparer les performances des méthodes suggérées. Mais quelque chose me dit que Join gagnera :)
la source
using System.Linq;
est requis.Bien que l'OP ait spécifié .NET 3.5, les personnes souhaitant le faire dans .NET 2.0 avec C # 2 peuvent le faire:
Je trouve qu'il existe un certain nombre d'autres cas où l'utilisation des fonctions Convert.xxx est une alternative plus intéressante à un lambda, bien qu'en C # 3, le lambda puisse aider l'inférence de type.
Une version C # 3 assez compacte qui fonctionne avec .NET 2.0 est la suivante:
la source
Un mélange des deux approches consisterait à écrire une méthode d'extension sur IEnumerable <T> qui utilise un StringBuilder. Voici un exemple, avec des surcharges différentes selon que vous souhaitez spécifier la transformation ou simplement compter sur ToString brut. J'ai nommé la méthode "JoinStrings" au lieu de "Join" pour éviter toute confusion avec l'autre type de Join. Peut-être que quelqu'un peut trouver un meilleur nom :)
la source
Nous devons convertir chacun des éléments en un
String
avant de pouvoir les joindre, il est donc logique d'utiliserSelect
et une expression lambda. Ceci est équivalent àmap
dans certaines autres langues. Ensuite, nous devons reconvertir la collection résultante de chaînes en un tableau, carString.Join
n'accepte qu'un tableau de chaînes.Le
ToArray()
est un peu moche je trouve.String.Join
devrait vraiment accepterIEnumerable<String>
, il n'y a aucune raison de le limiter aux seuls tableaux. C'est probablement juste parce queJoin
c'est avant les génériques, quand les tableaux étaient le seul type de collection typée disponible.la source
Si votre tableau d'entiers peut être volumineux, vous obtiendrez de meilleures performances en utilisant un StringBuilder. Par exemple:
Edit: Quand j'ai posté ceci, j'avais l'impression erronée que "StringBuilder.Append (valeur int)" a réussi en interne à ajouter la représentation sous forme de chaîne de la valeur entière sans créer d'objet string. C'est faux: l'inspection de la méthode avec Reflector montre qu'elle ajoute simplement value.ToString ().
Par conséquent, la seule différence de performances potentielle est que cette technique évite la création d'un tableau et libère les chaînes pour le garbage collection un peu plus tôt. En pratique, cela ne fera aucune différence mesurable, j'ai donc voté pour cette meilleure solution .
la source
La question est de savoir "le moyen le plus simple de les convertir en une seule chaîne où les nombres sont séparés par un caractère".
Le moyen le plus simple est:
EDIT: Cela ne fonctionne que dans .NET 4.0+, j'ai manqué l'exigence .NET 3.5 la première fois que j'ai lu la question.
la source
Je suis d'accord avec l'expression lambda pour la lisibilité et la maintenabilité, mais ce ne sera pas toujours la meilleure option. L'inconvénient d'utiliser à la fois les approches IEnumerable / ToArray et StringBuilder est qu'ils doivent développer dynamiquement une liste, soit d'éléments, soit de caractères, car ils ne savent pas combien d'espace sera nécessaire pour la chaîne finale.
Si le cas rare où la vitesse est plus importante que la concision, ce qui suit est plus efficace.
la source
J'ai aussi pensé qu'il y avait un moyen plus simple. Vous ne connaissez pas la performance, quelqu'un a une idée (théorique)?
la source
Substring(1)
pour résoudre ce problème (c'était de mémoire).Dans .NET 4.0, la jointure de chaîne a une surcharge pour
params object[]
, donc c'est aussi simple que:exemple
Dans .NET 2.0, c'est un tout petit peu plus difficile, car il n'y a pas de telle surcharge. Vous avez donc besoin de votre propre méthode générique:
Dans .NET 3.5, vous pouvez utiliser des méthodes d'extension:
Vous pouvez donc utiliser la méthode d'extension JoinArray.
Vous pouvez également utiliser cette méthode d'extension dans .NET 2.0, si vous ajoutez ExtensionAttribute à votre code:
la source
Tu peux faire
Check-out
ToString délimité par un séparateur pour tableau, liste, dictionnaire, IEnumerable générique
la source