379 votes

Utiliser LINQ pour concaténer des chaînes de caractères

Quelle est la manière la plus efficace d'écrire le texte de l'ancienne école :

StringBuilder sb = new StringBuilder();
if (strings.Count > 0)
{
    foreach (string s in strings)
    {
        sb.Append(s + ", ");
    }
    sb.Remove(sb.Length - 2, 2);
}
return sb.ToString();

... en LINQ ?

1 votes

Avez-vous découvert d'autres façons super cool de faire les choses avec LINQ ?

3 votes

La réponse sélectionnée et toutes les autres options ne fonctionnent pas avec Linq to Entities.

3 votes

@Binoj Antony, ne faites pas concaténer des chaînes de caractères dans votre base de données.

559voto

smink Points 39640

Cette réponse montre l'utilisation de LINQ ( Aggregate ) comme demandé dans la question et n'est pas destiné à un usage quotidien. Parce qu'il n'utilise pas de StringBuilder il aura des performances horribles pendant de très longues séquences. Pour le code normal, utilisez String.Join comme indiqué dans l'autre répondre

Utilisez des requêtes agrégées comme celles-ci :

string[] words = { "one", "two", "three" };
var res = words.Aggregate(
   "", // start with empty string to handle empty list case.
   (current, next) => current + ", " + next);
Console.WriteLine(res);

Cette sortie :

, one, two, three

Un agrégat est une fonction qui prend une collection de valeurs et renvoie une valeur scalaire. Les exemples de T-SQL incluent min, max et sum. VB et C# prennent tous deux en charge les agrégats. VB et C# prennent en charge les agrégats en tant que méthodes d'extension. En utilisant la notation par points, il suffit d'appeler une méthode sur un agrégat IEnumerable objet.

N'oubliez pas que les requêtes agrégées sont exécutées immédiatement.

Plus d'informations - MSDN : Requêtes agrégées


Si vous voulez vraiment utiliser Aggregate variante d'utilisation utilisation StringBuilder proposé en commentaire par CodeMonkeyKing ce qui correspondrait à peu près au même code qu'un String.Join y compris de bonnes performances pour un grand nombre d'objets :

 var res = words.Aggregate(
     new StringBuilder(), 
     (current, next) => current.Append(current.Length == 0? "" : ", ").Append(next))
     .ToString();

4 votes

Le premier exemple ne produit pas "un, deux, trois", mais ", un, deux, trois" (remarquez la virgule qui précède).

0 votes

Dans votre premier exemple, puisque vous commencez avec "" la première valeur utilisée dans current est une chaîne vide. Ainsi, pour 1 ou plusieurs éléments, vous obtiendrez toujours , au début de la chaîne.

0 votes

@Mort J'ai corrigé cela

414voto

David B Points 53123
return string.Join(", ", strings.ToArray());

Dans .Net 4, il y a une nouvelle fonction surcharge para string.Join qui accepte IEnumerable<string> . Le code se présenterait alors comme suit :

return string.Join(", ", strings);

2 votes

OK, la solution n'utilise pas Linq, mais elle me semble fonctionner assez bien

24 votes

C'est la réponse la plus correcte. Elle est plus rapide que la question et que la réponse acceptée et elle est beaucoup plus claire que l'agrégat, qui nécessite une explication d'un paragraphe à chaque fois qu'il est utilisé.

133voto

Armin Ronacher Points 16894

Pourquoi utiliser Linq ?

string[] s = {"foo", "bar", "baz"};
Console.WriteLine(String.Join(", ", s));

Cela fonctionne parfaitement et accepte n'importe quel IEnumerable<string> pour autant que je m'en souvienne. Il n'est pas nécessaire Aggregate rien ici, ce qui est beaucoup plus lent.

21 votes

Apprendre LINQ peut être cool, et LINQ peut être un moyen mignon d'atteindre le but, mais utiliser LINQ pour obtenir le résultat final serait pour le moins mauvais, si ce n'est carrément stupide

10 votes

.NET 4.0 dispose d'une surcharge IEnumerable<string> et IEnumrable<T>, ce qui facilitera grandement l'utilisation de l'option

3 votes

Comme le souligne Cine, .NET 4.0 a la surcharge. Ce n'est pas le cas des versions précédentes. Vous pouvez toujours String.Join(",", s.ToArray()) dans les anciennes versions.

79voto

Robert S. Points 15449

Avez-vous examiné la méthode d'extension Aggregate ?

var sa = (new[] { "yabba", "dabba", "doo" }).Aggregate((a,b) => a + "," + b);

25 votes

C'est probablement plus lent que String.Join(), et plus difficile à lire dans le code. Mais cela répond à la question de la "méthode LINQ" :-)

6 votes

Oui, je ne voulais pas entacher la réponse avec mes opinions :P

2 votes

Il est incontestablement un peu plus lent. Même l'utilisation de Aggregate avec un StringBuilder au lieu de la concaténation est plus lente que String.Join.

58voto

Daniel Earwicker Points 63298

Exemple concret tiré de mon code :

return selected.Select(query => query.Name).Aggregate((a, b) => a + ", " + b);

Une requête est un objet qui possède une propriété Nom qui est une chaîne de caractères, et je veux les noms de toutes les requêtes de la liste sélectionnée, séparés par des virgules.

2 votes

Compte tenu des commentaires sur les performances, je dois ajouter que l'exemple provient d'un code qui s'exécute une fois lorsqu'une boîte de dialogue se ferme, et qu'il est peu probable que la liste contienne plus d'une dizaine de chaînes de caractères !

0 votes

Une idée sur la manière d'effectuer cette même tâche avec Linq to Entities ?

1 votes

Excellent exemple. Merci de l'avoir transposé dans un scénario réel. J'ai eu exactement la même situation, avec une propriété d'un objet qui avait besoin d'être concaténée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X