2008-10-03 14 views
14

Jakie jest funkcjonalne podejście do programowania konwersji IEnumerable<string> na rozdzielany ciąg? Wiem, że mogę użyć pętli, ale staram się owijać głowę wokół programowania funkcjonalnego.C# - IEnumerable to delimited string

Oto mój przykład:

var selectedValues = 
from ListItem item in checkboxList.Items 
where item.Selected 
select item.Value; 

var delimitedString = ?? 

.. czy mogę to zrobić tylko w pierwszym przypisania var (dołączyć każdy wynik do poprzedniego)?

Odpowiedz

17
var delimitedString = selectedValues.Aggregate((x,y) => x + ", " + y); 
+6

To będzie bardzo kosztowne pod względem pośrednich ciągów. Bardzo FP, ale niezbyt praktyczny. http://www.yoda.arachsys.com/csharp/stringbuilder.html –

+4

@Marc, odpowiedziałem na zadane pytanie, chodziło o FP, a nie o wydajność. –

31
string.Join(", ", string[] enumerable) 
+2

+1, ale powiedziałbym string.join ("", selectedValues.ToArray()) – Lucas

+2

@Lucas, jeśli nie używasz .NET 4. http://msdn.microsoft.com/en-us/library/dd992421.aspx –

+0

@Omer, true! ale to było w październiku 2008 roku, przed .NET 4 :) – Lucas

4
var delimitedString = string.Join(",", checkboxList.Items.Where(i => i.Selected).Select(i => i.Value).ToArray()); 
2

Cóż, w tym przypadku podejście funkcjonalne może nie być najlepsza, po prostu dlatego, że nie jest to LINQ „ForEach”, a nie chcesz korzystać ciąg konkatenacji: chcesz użyj StringBuilder. Można użyć ToArray (przykładem właśnie pojawiła się powyżej), ale byłbym skłonny do wystarczy użyć:

StringBuilder sb = new StringBuilder(); 
    foreach(ListViewItem item in checkboxList.SelectedItems) { 
     if(sb.Length > 0) sb.Append(','); 
     sb.Append(item.Text); 
    } 
    string s = sb.ToString(); 

Not programowanie funkcjonalne, ale działa ... oczywiście, jeśli źródłem jest już string [], a następnie string.Join jest idealny. (LINQ jest doskonałym narzędziem, ale niekoniecznie zawsze najlepszym narzędziem do każdego zadania)

1

Oto LINQ/funkcjonalny sposób to zrobić.


string[] toDelimit = CallSomeFunction(); 
return toDelimit.Aggregate((x, y) => x + "," + y); 
3

AviewAnew jest najlepszą odpowiedzią, ale jeśli to, co szukasz jest nauczenie się myśleć w funkcjonalny, co należy zrobić, to użyć krotny operację (lub kruszywo, jak nazywa się w Sieci).

items.Aggregate((accum, elem) => accum + ", " + elem); 
+0

Czy string.join jest lepszy ze względu na wydajność? Powiedziałbym, że lepiej z punktu widzenia czytelności. – Jeremy

+0

Powiedziałbym tak; .ToArray() [aby uzyskać ciąg []] użyje podwojenia, więc nie wiele pośrednich tablic - a następnie string.Join jest w zasadzie StringBuilder; jednak ciąg łączenia łańcuchów będzie miał za każdym razem nowy ciąg, tak teleskopowy w rozmiarze. –

+0

Zgadzam się, jest to rodzaj rozwiązania, które można znaleźć w funkcjonalnym języku programowania (takim jak haskell), ale nie tutaj. Ale chwytanie foldr jest jednym z kluczy do opanowania języków funkcjonalnych. –

23

Oto przykład z StringBuilder. Ciekawe, że Append() zwraca samą instancję StringBuilder.

return list.Aggregate(new StringBuilder(), 
           (sb, s) => 
           (sb.Length == 0 ? sb : sb.Append(',')).Append(s)); 
+0

ostatni wiersz powinien prawdopodobnie być (sb.Length == 0 sb.Append (s): sb.Append (", ')) .Append (s)); – Tormod

0

to 3,5 kompatybilne:

var selectedValues = String.Join(",", (from ListItem item in checkboxList.Items where item.Selected select item.Value).ToArray());