2009-08-24 5 views
2

dire que j'ai un generic dictionary avec des données comme celle-ci (j'espère que la notation est clair ici):en utilisant Enumerable.Aggregate sur System.Collection.Generic.Dictionary

{ "param1" => "value1", « param2 » => « valeur2 », « param3 » => « value3 » }

J'essaie d'utiliser la fonction Enumerable.Aggregate pour se replier sur chaque entrée dans le dictionnaire et quelque chose sortie comme ceci:

"/ param1 = valeur1;/param2 = valeur2;/param3 = v alue3 "

Si j'agrégeais une liste, ce serait facile. Avec le dictionnaire, les paires clé/valeur me font trébucher.

Répondre

8

Vous n'avez pas besoin Aggregate:

String.Join("; ", 
    dic.Select(x => String.Format("/{0}={1}", x.Key, x.Value)).ToArray()) 

Si vous voulez vraiment l'utiliser:

dic.Aggregate("", (acc, item) => (acc == "" ? "" : acc + "; ") 
         + String.Format("/{0}={1}", item.Key, item.Value)) 

Ou:

dic.Aggregate("", 
    (acc, item) => String.Format("{0}; /{1}={2}", acc, item.Key, item.Value), 
    result => result == "" ? "" : result.Substring(2)); 
+0

Merci! En regardant le code dic.agrgregate, je vois pourquoi la solution String.Join est mieux adaptée pour cela. – brad

+0

Mais la méthode 'String.Join' ne marche-t-elle pas deux fois sur le dictionnaire (une fois pour configurer le tableau et une seconde fois pour rejoindre les éléments du tableau)? Vous créez également un tableau jetable lorsque vous pouvez tout aussi bien joindre votre chaîne que vous marchez sur les éléments. – paracycle

+1

paracycle: Si la performance est au premier plan, vous devriez probablement utiliser quelque chose comme 'StringBuilder' dans une boucle mais même si ce n'est pas le cas, utiliser 'Join' allouera une seule chaîne de caractères et y copiera toutes les chaînes du tableau. probablement plus efficace que de concaténer chaque partie de la ficelle et de la jeter. L'opération de concat est dans l'agrégat O (n^2) où n est la longueur de la chaîne de sortie. –

1

Je crois que cela répond à vos besoins:

 var dictionary = new Dictionary<string, string> {{"a", "alpha"}, {"b", "bravo"}, {"c", "charlie"}}; 
     var actual = dictionary.Aggregate("", (s, kv) => string.Format("{0}/{1}={2}; ", s, kv.Key, kv.Value)); 
     Assert.AreEqual("/a=alpha; /b=bravo; /c=charlie; ", actual); 
+0

Cela vous laisserait avec un ";" à la fin cependant. La plupart du temps (et aussi pour la question originale, semble-t-il) ce n'est pas souhaitable. – paracycle

+0

Inclut un ";" supplémentaire, vous devrez supprimer. Fonctionne quand même. –

+0

Vous pouvez utiliser le sélecteur de résultat pour prendre en charge cette entrée de fin: var réel = dictionary.Aggregate ("", (s, kv) => chaîne.Format ("{0}/{1} = {2} ; ", s, kv.Key, kv.Value), s => s.TrimEnd ('') .TrimEnd (';')); – neontapir

0

Je pense que ce que vous cherchez est quelque chose comme ceci:

var str = dic.Aggregate("", (acc, item) => { 
    if (acc != "") 
     acc += "; "; 

    acc += "/" + item.Key + "=" + item.Value; 

    return acc; 
}); 
+1

Ne fonctionne pas. Vous devez retourner 'acc'. –

+0

C'est ce que vous obtenez pour passer de la simple syntaxe lambda à un corps de fonction à la dernière minute. :) – paracycle

Questions connexes