2009-12-17 5 views
2

Dites que j'ai une liste d'objets, et l'objet a une propriété de chaîne. Je veux obtenir une seule liste séparée par des virgules de la valeur de chaque propriété de chaîne de chaque objet dans la liste. est ici 1 façon de le faire (sans LINQ)Une autre question Linqification

 

StringBuilder result = new StringBuilder() 
foreach(myObject obj in myList) 
{ 
    result.Append(obj.TheString); 
    result.Append(", "); 
} 
// then trim the trailing ", " and call ToString() on result, etc, etc... 
 

Voici mon premier coup linqification. Y a-t-il un meilleur moyen?

 

string result = string.Join(", ", myList.Select(myObj => myObj.TheString).ToArray()); 
 

C'est une ligne de code, mais il ne semble pas très efficace pour moi - itérer la liste juste pour construire un tableau, juste pour itérer le tableau et construire une chaîne ... ouf!

Y a-t-il un meilleur moyen?

Répondre

5

Si vous voulez efficace, utilisez Enumerable.Aggregate avec StringBuilder:

string result = myList.Aggregate(new StringBuilder(), 
           (sb, o) => sb.Append(o.TheString).Append(", ")) 
         .ToString(); 

Le problème initial est que String.Join veut un tableau. En .NET 4, il y aura une surcharge qui prendra IEnumerable<string> (et je m'attends à ce qu'il soit implémenté comme ci-dessus).

+0

+1 Vraiment profiter des réponses comme ça qui montrent ce que Linq peut faire! Cela me fascine que vous pouvez définir le type de résultat à StringBuilder (bien sûr après avoir supprimé .ToString()) et définir un point d'arrêt, et trouver l'évaluation Linq a été faite avant de convertir en chaîne ... ce qui ajoute à ma confusion à propos de -appelé "évaluation différée" dans Linq ... mais ce n'est pas votre problème! :) J'ai enveloppé votre solution dans une méthode, puis utilisé StringBuilder.Remove pour se débarrasser de l'espace supplémentaire et de la virgule avant de convertir en chaîne. Expérimentera en faisant ceci dans une méthode d'extension. Merci ! – BillW

+0

L'évaluation différée est différée pour produire 'StringBuilder', mais' StringBuilder' n'est pas différé - bien que rien n'empêche d'écrire un 'StringBuilder' paresseux aussi (et en théorie il est tout à fait possible d'avoir des ficelles basiques aussi, bien que cela aurait besoin du soutien du CLR). –

1

J'aime cette méthode d'extension pour joindre des chaînes. C'est essentiellement la même technique que vous utilisez, mais enveloppé dans une méthode d'extension. Je ne le recommanderais pas pour les grands ensembles puisque l'efficacité n'était pas l'objectif. L'avantage pour moi est expressivité (très linqy) et pratique pour les petits ensembles:

[Test] 
public void Should_make_comma_delimited_list() 
{ 
    var colors = new List<HasColor> 
    { 
     new HasColor { Color = "red" }, 
     new HasColor { Color = "green" }, 
     new HasColor { Color = "blue" } 
    }; 

    var result = colors.Implode(x => x.Color, ", "); 

    Assert.That(result, Is.EqualTo("red, green, blue")); 
} 

public class HasColor 
{ 
    public string Color { get; set; } 
} 

public static class LinqExtensions 
{ 
    public static string Implode<T>(this IEnumerable<T> list, Func<T, string> func, string separator) 
    { 
     return string.Join(separator, list.Select(func).ToArray()); 
    } 
} 
+0

+1 Apprécié! – BillW

0

est ici une autre façon (result est un StringBuilder):

myList.ForEach(
    myObj => 
    { 
     if (result.Length != 0) 
      result.Append(","); 
     result.Append(myObj.TheString); 
    } 
    ); 
1

Utilisez string.join, il est assez bon.

Optimisez lorsque profiler vous dira de le faire.

La lisibilité de la version avec StringBuilder est médiocre et vous obtenez toujours la virgule de fin.